正则表达式学习2 - 零宽断言

参考文章:https://deerchao.net/tutorials/regex/regex.htm#backreference

这篇看起来像是图书一样:http://www.ha97.com/book/OpenSource_Guide/ch26s09.html

当该字符("?")紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。

零宽断言

(?=exp) 	匹配exp前面的位置
(?<=exp) 	匹配exp后面的位置
(?!exp) 	匹配后面跟的不是exp的位置
(?<!exp) 	匹配前面不是exp的位置

(?=exp)

(?=exp)也叫零宽度正预测先行断言,它断言自身出现的位置的后面能匹配表达式exp。比如\b\w+(?=ing\b),匹配以ing结尾的单词的前面部分(除了ing以外的部分),如查找I'm singing while you're dancing.时,它会匹配sing和danc。

如果不想匹配符号,只匹配一个位置,就要用到“零宽断言”(匹配宽度为零,满足一定的 条件/断言),零宽断言使用 (?=表达式) 的语法,例如 \w+(?=。),其中 (?=。) 表示 前面的位置(先行断言)

要我说,这个可以这么看:

表达式:exp1(?=exp2),相当于exp1exp2,只是获取的时候,只拿exp1,而exp2不进入获取行列。且exp2只要拿到最基础的一个匹配就可以了。这里采用的是非贪婪模式。

当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。

例1:

表达式\w+(?=[\d+])

1.匹配字符串ab1cd22

结果:

共找到 1 处匹配:
ab1cd2
流程:exp1=\w+,exp2=[\d+],exp=exp1+exp2=\w+\d+,根据exp表达式匹配得到ab1cd22,然后匹配掉一个exp2即[\d+](最尾部的匹配到一个符合的就结束),得到exp2匹配字符串2(采用的是非贪婪模式,只要基础匹配就可以了),而不是22,从而最终得到结果ab1cd22-2= ab1cd2。由于exp1和exp2有重叠的表达式\d+,所以结果看起来有些绕。
2.匹配字符串abcd

结果:无任何匹配

流程:因为根本就没有符合exp=\w+\d+的字符串

 

例2:

表达式:[a-z](?=\d)

1.匹配字符串a1bc2

结果:

共找到 2 处匹配:
a
c
流程:exp=[a-z]\d,a1匹配到,获取a,继续往下,直到c2匹配到,获取c

 

例3:

在菜鸟教程里面看到一个正则表达式,^(?=.*[A-Z])(?=.*[a-z])(?=.*\d).{4},瞬间就懵逼了,完全不能理会为什么是用来确定一串字符串一定是由大小写字母以及数字组成的四位。

进行拆解:

1.表达式如果是^.{4}(?=.*[A-Z])那么,即和表达式^.{4}([A-Z])结果一致。毕竟采用的是非贪婪获取。

2.表达式如果是^(?=.*[A-Z]).{4},那么意味着匹配字符串需要先符合[A-Z]条件,然后整个字符串就能够继续下一步匹配了。

例如:A1234,结果:A123。由于第一个字符A的匹配,所以接下来,A123匹配到了.{4},因为?=不进行获取字符。

3.表达式如果是(?=[A-Z])(?=[a-z]).{4},这个表达式匹配不到任何东西。按照逻辑来看,第一步是找到[A-Z],符合[A-Z]后,需要符合[a-z]的,但由于前面多了个[A-Z]的匹配,从而导致两项冲突。

应该修改为(?=[A-Z])(?=.*[a-z]).{4},如此就能够进行匹配[A-Z][a-z].{2}类型的对象,主要是.*能够将前面匹配的[A-Z]匹配到的给抵消掉。

eg:Aaaa,Aa12,AaAA...

那么最后来看表达式:^(?=.*[A-Z])(?=.*[a-z])(?=.*\d).{4} ,意思就明确了,必须匹配[A-Z],[a-z],[\d]任何一个,至于匹配到的对象因为?=的写法,所以并不会被获取到结果中去,而为了三个同时匹配,所以添加了(.*)用以消除另外的零宽断言的影响。只要字符串中存在大小写字母以及数字(每个都得有一个字符)即可,将会获取到四个字符

 

 

(?<=exp)------------------这个大概已经淘汰了,正则表达式测试测不出来

(?<=exp)也叫零宽度正回顾后发断言,它断言自身出现的位置的前面能匹配表达式exp。比如(?<=\bre)\w+\b会匹配以re开头的单词的后半部分(除了re以外的部分),例如在查找reading a book时,它匹配ading。

 

如果需要匹配后面的位置,如:

regularexpression  

则要用到后发断言 (?<=。) ,使用 (?<=。)\w+ 得到上面的匹配结果

使用 (?<=<b>).*(?=</b>) 匹配标签中的内容

<b>粗体</b>  

 

posted @ 2017-05-11 16:34  Danlis  阅读(311)  评论(0编辑  收藏  举报