断言

  判断某个位置左侧或者右侧是否符合匹配。常见断言有三种,单词边界、行起始/结束位置、环视。阅读本章前,建议先下载我于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. pt-online-schema-change中update触发器的bug

    pt-online-schema-change在对表进行表结构变更时,会创建三个触发器. 如下文测试案例中的t2表,表结构如下: mysql> show create table t2\G . ...

  2. select、poll、epoll之间的区别总结

    select.poll.epoll之间的区别总结 05/05. 2014 select,poll,epoll都是IO多路复用的机制.I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪 ...

  3. C#——传值参数(1)

    //我的C#是跟着猛哥(刘铁猛)(算是我的正式老师)<C#语言入门详解>学习的,微信上猛哥也给我讲解了一些不懂得地方,对于我来说简直是一笔巨额财富,难得良师! 这次与大家一起学习C#中的值 ...

  4. BPM SharePoint解决方案分享

    一.需求分析 SharePoint作为微软推出的协同类平台产品,为客户提供了门户.内容.文档.流程.社区.搜索.BI等一系列的解决方案,然而其流程功能由于设计理念差异,不能完全满足客户的需求,主要原因 ...

  5. Android 关于ijkplayer

    基于ijkplayer封装支持简单界面UI定制的视频播放器 可以解析ts格式的so库 怎样编译出可以解析ts等格式的so库?就是编译的时候需要在哪一步修改配置? 一些电视台的m3u8 CCTV1综合, ...

  6. ORA-00821: Specified value of sga_target 3072M is too small, needs to be at least 12896M

    在测试PlateSpine克隆的数据库服务器时,由于资源有限,克隆过来的数据库服务器只给了9G的内存,结果在测试时,老是会出现OOMkiller导致宕机,即out of memory killer,是 ...

  7. [AlwaysOn Availability Groups] 健康模型 Part 2 ——扩展

    健康模型扩展 第一部分已经介绍了AlwayOn健康模型的概述.现在是创建一个自己的PBM策略,然后设置为制定的归类.创建这些策略,创建之后修改一下配置,dashboard就会自动评估这些策略. 场景, ...

  8. 在VMware上安装CentOS -7

    1.下载好VMware 2.准备好CentOS的镜像文件 3.打开VMware创建新的虚拟机 选择自定义高级后按下一步 继续下一步 选择稍后安装操作系统 客户机操作系统选择Linux,版本选择Cent ...

  9. 归并排序的java实现

    归并排序的优点不说了. 做归并排序之前,我先试着将两个有序数组进行排序,合并成一个有序数组. 思路:定义好两个有序数组,理解的时候我先思考了数组只有一个数组的排序,然后是两个元素的数组的排序,思路就有 ...

  10. java中判断字符串是否为只包含数字

    1.用Java自带的函数 public static boolean isNumeric(String str){ for(int i=str.length();--i>=0;){ if (!C ...