深入理解正则表达式的环视

从Zjmainstay的深入理解正则表达式高级教程中截取的一部分内容:
环视(断言/零宽断言)

环视,在不同的地方又称之为零宽断言,简称断言。 
用一句通俗的话解释: 
环视,就是先从全局环顾一遍正则,(然后断定结果,)再做进一步匹配处理。 
断言,就是先从全局环顾一遍正则,然后断定结果,再做进一步匹配处理。

两个虽然字面不一样,意思却是同一个,都是做全局观望,再做进一步处理。

环视的作用相当于对其所在位置加了一个附加条件,只有满足这个条件,环视子表达式才能匹配成功

环视主要有以下4个用法: 
(?<=exp) 匹配前面是exp的数据 
(?<!exp) 匹配前面不是exp的数据 
(?=exp) 匹配后面是exp的数据 
(?!exp) 匹配后面不是exp的数据

示例四: 
(?<=B)AAA 匹配前面是B的数据,即BAAA匹配,而CAAA不匹配 
(?<!B)AAA 匹配前面不是B的数据,即CAAA匹配,而BAAA不匹配 
AAA(?=B) 匹配后面是B的数据,即AAAB匹配,而AAAC不匹配 
AAA(?!B) 匹配后面不是B的数据,即AAAC能匹配,而AAAB不能匹配

另外,还会看到(?!B)[A-Z]这种写法,其实它是[A-Z]范围里,排除B的意思,前置的(?!B)只是对后面数据的一个限定,从而达到过滤匹配的效果。

因此,环视做排除处理是比较实用的,比如,示例五:

需求:字母、数字组合,不区分大小写,不能纯数字或者纯字母,6-16个字符。
通用正则:^[a-z0-9]{6,16}$    字母数字组合,6-16个字符
    排除纯字母:(?!^[a-z]+$)
排除纯数字:(?!^[0-9]+$)
    组合起来:(?!^[a-z]+$)(?!^[0-9]+$)^[a-z0-9]{6,16}$

注意,环视部分是不占宽度的,所以有零宽断言的叫法。 
所谓不占宽度,可以分成两部分理解: 
1、环视的匹配结果不纳入数据结果 
2、环视它匹配过的地方,下次还能用它继续匹配。

如果不是环视,则匹配过的地方,不能再匹配第二次了。

上面示例四体现了:环视的匹配结果不纳入数据结果,它的结果:

 
 
  1. (?<=B)AAA 源串:BAAA 结果:AAA
  2. (?<!B)AAA 源串:CAAA 结果:AAA
  3. AAA(?=B) 源串:AAAB 结果:AAA
  4. AAA(?!B) 源串:AAAC 结果:AAA

而示例五体现了:环视它匹配过的地方,下次还能用它继续匹配 
因为,整个匹配过程中,正则表达式一共走了3次字符串匹配,第一次匹配不全部是字母,第二次匹配不全部是数字,第三次匹配全部是字母数字组合,6-16个字符。

 
 
  1. 扩展部分:
  2. `[A-Z](?<=B)` [A-Z]范围等于B
  3. `[A-Z](?<!B)` [A-Z]范围排除B
  4. `(?!B)[A-Z]` [A-Z]范围排除B

附: js不支持(?<=exp) 和 (?<!exp) 语法

猜你喜欢

转载自blog.csdn.net/piglite/article/details/79072391