断言

  判断某个位置左侧或者右侧是否符合匹配。常见断言有三种,单词边界、行起始/结束位置、环视。阅读本章前,建议先下载我于CSDN上传的示例代码,下载无需分数,下载链接

1.单词边界

  正则表达式"\b"用于匹配单词的边界。实际上他匹配一个这样的位置,这个位置一边匹配"\w",一边不匹配"\w"。例如,输入字符串"I Love China!",若用正则表达式"\b\w+\b"来匹配,则能捕获子字符串"I","Love","China"。

2.行起始/结束位置

  行起始位置可用"^"匹配,行结束位置可用"$"匹配。这个看起来十分简单,但是有一点需要十分注意。当他们在单行模式下和在多行模式下能匹配的位置是不同的。起初在我学习正则表达式时,误以为单行模式是将输入的字符串看成是单行的,多行模式则看成多行。其实后来通过代码的测试并且看了一些其他的博客,才理解其实单行模式和多行模式,只是影响某一些正则表达式字符所能匹配的字符串而已。下面做出我对单行模式和多行模式的理解。

  首先,通过看资料得知在Windows平台下,每一行的换行符总是"\r\n"这样的。而其他平台的换行符则是"\n"这样的。

  单行模式下,"^"比较简单,即匹配文本的最开始的位置,不管你这个输入文本是单行的还是多行的。多行模式下,"^"除了具有单行模式的能力外,还能匹配"\n"之后的位置。但是不能匹配"\r"后面的位置,当时看了某篇博文误导了好久。Regex类下的Replace方法,对匹配的字符串替换成你想要的字符串。若匹配的是位置,这实际上是在该位置上添加你想要的字符串。  

Regex regex = new Regex("^");//默认所有都为单行模式
string replace = regex.Replace("abc\n", "|");//"|abc\n" 该值通过断点得出而非控制台
regex = new Regex("^", RegexOptions.Multiline);//多行模式
replace = regex.Replace("abc\n", "|");//"|abc\n|" 该值通过断点得出而非控制台

  单行模式下,"$"匹配文本的最后位置,其实这里说最后位置是不准确的,我无法给出一个准确的词语描述,只能同过代码来让你们注意某些事情。多行模式下,同样除了具有单行模式的能力外还能匹配"\n"之前的位置,并且也是不能匹配"\r"前面的位置。

Regex regex = new Regex("$");//默认所有都为单行模式
string replace = regex.Replace("abc\nabc\n", "|");//"abc\nabc|\n|" 该值通过断点得出而非控制台
replace = regex.Replace("abc\nabc\nabc", "|");//"abc\nabc\nabc|" 该值通过断点得出而非控制台
regex = new Regex("$", RegexOptions.Multiline);//多行模式
replace = regex.Replace("abc\nabc\n", "|");//"abc|\nabc|\n|" 该值通过断点得出而非控制台

  看到以上结果了吗,单行模式下的"$",如果是以"\n","\r\n"结尾的,除了匹配他们之后的位置,也会匹配他们之前的位置,导致得出第一个replace的结果。如果不以"\n","\r\n"结尾的则没有争议的在最后位置上匹配了。多行模式下同样有这个问题。为了解决这个问题,可以用"\z"来保证匹配字符串的最后一个位置,但是也不再有多行模式下的能力了。

Regex regex = new Regex(@"\z");//默认所有都为单行模式
string replace = regex.Replace("abc\nabc\n", "|");//"abc\nabc\n|" 该值通过断点得出而非控制台
replace = regex.Replace("abc\nabc\nabc", "|");//"abc\nabc\nabc|" 该值通过断点得出而非控制台
regex = new Regex(@"\z", RegexOptions.Multiline);//多行模式
replace = regex.Replace("abc\nabc\n", "|");//"abc\nabc\n|" 该值通过断点得出而非控制台

3.环视

  环视的作用是,当匹配到某个位置的时候,我们要确定该位置的左边或右边是否匹配我们设定的正则表达式,若是,则该位置匹配,继续完成后面的匹配,若否,则不匹配,也无需继续后面的匹配了。环视语法:往右环视,即顺序环视"(?=regStr)","(?!regStr)",其中"="表示肯定,"!"表示否定,即要不要匹配的问题。往左环视,即逆序环视"(?<=regStr)","(?<!regStr)"。

  例子1:外国人的数字通常喜欢用","去分隔,如有一个数字在中国是这样的"123456789",在过外就变成这样了"123,456,789"。我们可以总结出这样的规律,在这样一个位置上添加",",该位置的右边必须是3倍个数的数字,该位置的左边还必须有数字。这样,我们写出了正则表达式"(?<=\d)(?=(?:\d{3})+)"

Regex regex = new Regex(@"(?<=\d)(?=(?:\d{3})+)");
Console.WriteLine(regex.Replace("", ","));//1,2,3,4,5,6,789

  嗯,看来我们的思维还不够缜密,并不能一次编写正确的正则表达式,不过没关系,出现bug后我们可以立刻修正bug。导致这个bug的原因在于顺序环视时,当我们环视匹配完3倍个数的数字后,还必须保证他的后面再也没有数字了。找到问题的关键,我们来写出新的正则表达式"(?<=\d)(?=(?:\d{3})+(?!\d))"。在环视内部可以再嵌套一个环视。

Regex regex = new Regex(@"(?<=\d)(?=(?:\d{3})+(?!\d))");
Console.WriteLine(regex.Replace("", ","));//123,456,789
Console.WriteLine(regex.Replace("", ","));//1,234,567,890

  例子2:当我们得到一个这样无序的,包含数字和字母的字符串"1sf2sdf333sf55ew2156we98552af3sd5fas6654sdfa65assfd56"时,我们可以相当容易的用"\d+"来捕获其中的数字,但如果我不要求捕获这些数字,而是要求将数字用括号括起来,并将字符串返回怎么办。思路,我们要匹配的是一个位置,并在这个位置上加上括号。这个位置可以很简单的想到,他的一边是数字,一边不是数字。当然,我们要分两步实现这个功能,第一步,先用正则表达式"(?<!\d)(?=\d)"匹配数字开始的位置。第二部,用正则表达式"(?<=\d)(?!\d)"匹配数字结束的位置。是不是十分方便,用这么少的代码便完成了我们以前不敢想的功能。

Regex regex = new Regex(@"(?<!\d)(?=\d)");//匹配数字开头
string replace = "1sf2sdf333sf55ew2156we98552af3sd5fas6654sdfa65assfd56";
replace = regex.Replace(replace,"(");//"(1sf(2sdf(333sf(55ew(2156we(98552af(3sd(5fas(6654sdfa(65assfd(56"
regex = new Regex(@"(?<=\d)(?!\d)");//匹配数字结尾
replace = regex.Replace(replace, ")");//"(1)sf(2)sdf(333)sf(55)ew(2156)we(98552)af(3)sd(5)fas(6654)sdfa(65)assfd(56)"
Console.WriteLine(replace);

  断言暂时介绍这么多,谢谢!

.NET正则表达式基础入门(四)的更多相关文章

  1. .NET正则表达式基础入门

    这是我第一次写的博客,个人觉得十分不容易.以前看别人写的博客文字十分流畅,到自己来写却发现十分困难,还是感谢那些为技术而奉献自己力量的人吧. 本教程编写之前,博主阅读了<正则指引>这本入门 ...

  2. Swift语法基础入门四(构造函数, 懒加载)

    Swift语法基础入门四(构造函数, 懒加载) 存储属性 具备存储功能, 和OC中普通属性一样 // Swfit要求我们在创建对象时必须给所有的属性初始化 // 如果没办法保证在构造方法中初始化属性, ...

  3. C#基础入门 四

    C#基础入门 四 方法参数 值参数:不附加任何修饰符: 输出参数:以out修饰符声明,可以返回一个或多个给调用者: 如果想要一个方法返回多个值,可以用输出参数来处理,输出参数由out关键字标识,如st ...

  4. .NET正则表达式基础入门(一)

    字符组 正则表达式的字符组十分简单,就是列出你所想要匹配的字符.阅读本章前,建议先下载我于CSDN上传的示例代码,下载无需分数,下载链接. 1.普通字符组 普通字符组,列出所有你需要匹配的字符. 例如 ...

  5. .NET正则表达式基础入门(二)

    量词 正则表达式的量词用于表明前面的子表达式需要匹配的次数.阅读本章前,建议先下载我于CSDN上传的示例代码,下载无需分数,下载链接. 1.量词的一般形式 "{n}"," ...

  6. .NET正则表达式基础入门(三)

    括号 正则表达式中的括号能将多个字符或者表达式当做一组,即将他们看成一个整体.这样量词就可以修饰这一组表达式.阅读本章前,建议先下载我于CSDN上传的示例代码,下载无需分数,下载链接. 1.分组 假设 ...

  7. PHP正则表达式基础入门

    思维导图 介绍 正则表达式,大家在开发中应该是经常用到,现在很多开发语言都有正则表达式的应用,比如JavaScript.Java..Net.PHP 等,我今天就把我对正则表达式的理解跟大家唠唠,不当之 ...

  8. D3基础入门四-事件处理

    6.5.0版 .on("mouseover", function(e,d) e: {"isTrusted":true} 第二个参考才是数据,但这在不同的环境可能 ...

  9. Mybatis框架基础入门(四)--SqlMapConfig.xml配置文件简介

    SqlMapConfig.xml中配置的内容和顺序如下: properties(属性) settings(全局配置参数) typeAliases(类型别名) typeHandlers(类型处理器) o ...

随机推荐

  1. JavaScript动画-拖拽改变元素大小

    ▓▓▓▓▓▓ 大致介绍 拖拽改变元素大小是在模拟拖拽上增加了一些功能 效果:拖拽改变元素大小 ▓▓▓▓▓▓ 拖拽改变元素大小原理 首先这个方块得知道我们想要改变这个它的大小,所以我给它设定一个范围,当 ...

  2. C#多线程之线程池篇2

    在上一篇C#多线程之线程池篇1中,我们主要学习了如何在线程池中调用委托以及如何在线程池中执行异步操作,在这篇中,我们将学习线程池和并行度.实现取消选项的相关知识. 三.线程池和并行度 在这一小节中,我 ...

  3. 基于ASP.NET/C#开发国外支付平台(Paypal)学习心得。

        最近一直在研究Paypal的支付平台,因为本人之前没有接触过接口这一块,新来一家公司比较不清楚流程就要求开发两个支付平台一个是支付宝(这边就不再这篇文章里面赘述了),但还是花了2-3天的时间通 ...

  4. [C#] 回眸 C# 的前世今生 - 见证 C# 6.0 的新语法特性

    回眸 C# 的前世今生 - 见证 C# 6.0 的新语法特性 序 目前最新的版本是 C# 7.0,VS 的最新版本为 Visual Studio 2017 RC,两者都尚未进入正式阶段.C# 6.0 ...

  5. C++随笔:.NET CoreCLR之GC探索(4)

    今天继续来 带大家讲解CoreCLR之GC,首先我们继续看这个GCSample,这篇文章是上一篇文章的继续,如果有不清楚的,还请翻到我写的上一篇随笔.下面我们继续: // Initialize fre ...

  6. FILE文件流的中fopen、fread、fseek、fclose的使用

    FILE文件流用于对文件的快速操作,主要的操作函数有fopen.fseek.fread.fclose,在对文件结构比较清楚时使用这几个函数会比较快捷的得到文件中具体位置的数据,提取对我们有用的信息,满 ...

  7. HTTP API接口安全设计

    HTTP API接口安全设计 API接口调用方式 HTTP + 请求签名机制   HTTP + 参数签名机制 HTTPS + 访问令牌机制 有没有更好的方案? OAuth授权机制 OAuth2.0服务 ...

  8. DDD领域驱动设计 - 设计文档模板

    设计文档模板: 系统背景和定位 业务需求描述 系统用例图 关键业务流程图 领域语言整理,主要是整理领域中的各种术语的定义,名词解释 领域划分(分析出子域.核心域.支撑域) 每个子域的领域模型设计(实体 ...

  9. H3 BPM引擎API接口

    引擎API接口通过 Engine 对象进行访问,这个是唯一入口. 示例1:获取组织机构对象 this.Engine.Organization.GetUnit("组织ID"); 示例 ...

  10. Kotlin类:功能更强、而更简洁(KAD 03)

    作者:Antonio Leiva 时间:Dec 7, 2016 原文链接:http://antonioleiva.com/classes-kotlin/ Kotlin类尽可能简单,这样用较少的代码完成 ...