断言

  判断某个位置左侧或者右侧是否符合匹配。常见断言有三种,单词边界、行起始/结束位置、环视。阅读本章前,建议先下载我于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. 用scikit-learn学习DBSCAN聚类

    在DBSCAN密度聚类算法中,我们对DBSCAN聚类算法的原理做了总结,本文就对如何用scikit-learn来学习DBSCAN聚类做一个总结,重点讲述参数的意义和需要调参的参数. 1. scikit ...

  2. ES6的一些常用特性

    由于公司的前端业务全部基于ES6开发,于是给自己开个小灶补补ES6的一些常用特性.原来打算花两天学习ES6的,结果花了3天才勉强过了一遍阮老师的ES6标准入门(水好深,ES6没学好ES7又来了...) ...

  3. javascript设计模式:策略模式

    前言 策略模式有效利用组合.委托.多态等技术和思想,可以有效避免多重条件选择语句. 策略模式对开放-封闭原则提供了很好的支持,将算法封装在strategy中,使得他们易于切换.理解.扩展. 策略模式中 ...

  4. iOS - 模态Model视图跳转和Push视图跳转的混合需求实现原理

    在研发中总会遇到一些莫名的需求,本着存在即合理的态度跟大家分享一下"模态Model视图跳转和Push视图跳转的需求实现",本文仅仅传授研发技术不传授产品以及UE的思想,请大家合理对 ...

  5. Form 表单提交参数

    今天因为要额外提交参数数组性的参数给form传到后台而苦恼了半天,结果发现,只需要在form表单对应的字段html空间中定义name = 后台参数名 的属性就ok了. 后台本来是只有模型参数的,但是后 ...

  6. 安装并使用PHPunit

    安装并使用PHPunit Linux 下安装PHPunit PHP 档案包 (PHAR)  要获取 PHPUnit,最简单的方法是下载 PHPUnit 的 PHP 档案包 (PHAR),它将 PHPU ...

  7. 一步步开发自己的博客 .NET版(5、Lucenne.Net 和 必应站内搜索)

    前言 这次开发的博客主要功能或特点:    第一:可以兼容各终端,特别是手机端.    第二:到时会用到大量html5,炫啊.    第三:导入博客园的精华文章,并做分类.(不要封我)    第四:做 ...

  8. (转)利用libcurl获取新浪股票接口, ubuntu和openwrt实验成功(三)

    1.  利用 CURLOPT_WRITEFUNCTION 设置回调函数, 利用 CURLOPT_WRITEDATA 获取数据指针 官网文档如下 CALLBACK OPTIONS CURLOPT_WRI ...

  9. FreeBinary 格式说明

    说明 简称FB格式,是一个简单的二进制文件打包格式. 作用是FBX.unity.js等交换的一个中间格式. 由李剑英制定,易于读取,易于扩展 相应的代码可以用svn取得 SVN:http://code ...

  10. JVM虚拟机结构

    JVM的主要结构如下图所示,图片引用自舒の随想日记. 方法区和堆由所有线程共享,其他区域都是线程私有的 程序计数器(Program Counter Register) 类似于PC寄存器,是一块较小的内 ...