技术编程|30 分钟轻松搞定正则表达式基础( 三 )


分组
讲完中括号后我们可以看一下小括号() , 小括号的意思是分组 , 即小括号内部的所有元字符是一个整体 。
之前有学过表示数量的元字符 , 但是那个表示的数量都是针对于一个元字符来说的 , 比如ab+表示的是匹配一个a后面跟着1个或多个b的子字符串 。
倘若我们想要匹配的是1个或多个ab(如:abababab) , 此时分组就派上作用了 , 可以这么写:(ab)+ 。此时ab被绑定为一个整体 , 后面的数量元字符对这个整体起作用 。
分枝条件
元字符中有一个或运算符 , 它与大多数编程语言类似都是用 | 来表示 。它的作用为:Ab|aB表示的是匹配Ab或者aB 。通过这个例子可以很直观的理解该元字符的作用 。当然它也经常和分组一起使用:(Ab|aB)+c , 该正则匹配开始为1-N个Ab或aB之后是c的子字符串 , 如:AbaBc, AbAbAbaBc 。
后向引用
后向引用的使用是依附于分组的 , 分组的概念之前讲过了 。
首先 , 我们先看一下正则表达式中组号的分配方式 , 此时先看一个用到分组的正则表达式:(ab)?(c|C)d 。这个正则的意思大家现在肯定都清楚了 。这个正则表达式里面用到了两个分组分别是(ab)和(c|C) 。
正则内部会对所有分组进行组号分配 , 从左向右 , 第一个分组(ab)的组号是1 , 第二个分组(c|C)的组号是2 。而组号0代表的是整个正则表达式 。尝试过python正则的此处应该有印象 , 匹配对象的group方法传参为0或不传则返回整个正则所匹配的结果 , 传参为1为第一个分组匹配的结果 。
了解了组号分配方式后 , 可以开始解释后向引用了 。后向引用就是将前面某个分组已经匹配的数据拿过来用 , 第一个分组匹配的数据用\1代替 , 第二个分组匹配的数据用\2代替 , 依次类推 。
似乎不是特别好理解 , 直接看例子吧 , (ab)?(c|C)d\2D该正则中\2表示的是第二个分组匹配到的数据 , 若第二个分组匹配到了c那么\2就是c , 反之亦然 。所以它能匹配到:abcdcD, abCdCD 。不能匹配:abcdCD, abCdcD 。通过这个例子可以理解它的作用了吧 。
当然分组除了有自己的组号外 , 还可以给它自定义组名 。不同编程语言中的方式不同 , Python中自定义组名的格式为:(?P exp) , Name为你自定义的组名 , exp代表任意元字符的组合 。后面引用的方法为(?P=name) 。所以上面例子可以修改成:(ab)?(?P c|C)d(?P=CWord)D 。
组号分配介绍
上一节简单的讲了一下正则表达式是如何分配组号的 , 但其实还有几个需要注意的地方 。
虽然组号是从左向右进行分配 , 但是扫描两遍 , 第一遍先分配给未命名的分组 , 第二遍再分配给命名的分组 。所以命名后的分组组号会更大
使用(?:exp)可以使一个分组不分配组号 , 如(?:ab)?(c|C)d\2D中(ab)就没有分配到组号 , 而(c|C)组号为1
贪婪与懒惰
人性是贪婪的 , 正则表达式与人一样也是贪婪的 。一个正则表达式会尽量多的去匹配字符串 , 如:ab.+c去匹配’abccccc’是会将该字符串全部匹配出来 。但有时候我们只想要其匹配’abcc’ , 此时怎么办呢?需要给正则表达式中表示数量的元字符加一个?变成ab.+?c 。此时该正则表达式就变懒了 , 不会再去匹配那么多 , 匹配到‘abcc’就完事了 。
元字符说明
*?0个或多个 , 尽可能少+?1个或多个 , 尽可能少??0个或1个 , 尽可能少{n}?n个 , 尽可能少{n,}?n个或多个 , 尽可能少{n,m}?n到m个 , 尽可能少
零宽断言及负向零宽断言
这两个个概念有些不太好理解 。正如前面所说这两个也是表示位置的元字符 。从字面意思上理解 , 零宽代表其没有宽度 , 即如之前介绍表示位置的元字符中提到的一样 , 不会实际占用字符 。
断言是什么?是assert , 是用来判断条件是True还是False 。理解完这两个词语的意思后 , 零宽断言的概念应该也就能理解了 。那么负向无非就是它的反义词 。


推荐阅读