贪婪、非贪婪

    先看个小例子。
正则表达式为w*(d+),字符串为cfc456n,那么,这个正则匹配的$1是多少?如果您回答是 456,那么,恭喜你,回答了,其结果不是456,而是6,您知道为什么吗?

CFC4N来解释一下,当正则引擎用正则w*(d+)去 匹配字符串cfc456n时,会先用w*去匹配字符串cfc456n,首先,w*会匹配字符串cfc456n的所有字符,然后再交给d+去匹配剩下 的字符串,而剩下的没了,这时,w*规则会不情愿的吐出一个字符,给d+去匹配,同时,在吐出字符之前,记录一个点,这个点,就是用于回溯的 点,然后d+去匹配n,发现并不能匹配成功,会再次要求w*再吐出一个字符,w*会先再次记录一个回溯的点,再吐出一个字符。这时,w* 匹配的结果只有cfc45了,已经吐出6n了,d+再去匹配6,发现匹配成功,则会通知引擎,匹配成功了,就直接显示出来了。所以,(d+)的结果是 6,而不是456。

当上面的正则表达式改为 w*?(d+)(注意,此处为非贪婪),字符串仍然为cfc456n,那么,这时候,正则匹配的$1是多少??
甲同学回答:结果是 456。
嗯,是的,正确,是456,CFC4N弱弱的问下,为什么是456 呢?
我在来解释一下 为什么是456
正则表达式有条规则,是量词优先匹配,所以w*?会先去匹配字符串cfc456,由于w*?是非贪婪,正则引擎会用表达式w+?每次仅匹配一个字符 串,然后再将控制权交给后面的d+去匹配下一个字符,同时,记录一个点,用于在匹配不成功的时候,返回这里,再次匹配,也就是回溯点。由于w后面是量 词是*,*表示0到无数次,所以,首先是0次,也就是w*?匹配个空,记录回溯点,将控制权交给d+,d+去匹配cfc456n的第一个字符c,然 后,匹配失败,于是乎,接着讲控制权交给w*?去匹配cfc456n的c,w*?匹配c成功,由于是非贪婪,所以,他每次只匹配一个字符,记录回溯 点,然后再将控制权交给d+匹配f,接着,d+匹配f再失败,再把控制权给w*?,w*?再匹配c,记录回溯点(这时w*?匹配结果是cfc 了),再把控制权给d+,d+去匹配4,匹配成功,然后,由于量词是+,就是1到无数次,所以,接着往后匹配,再匹配5,成功,再接着,再匹配6,成 功,再接着,继续匹配操作,下一个字符是n,匹配失败,这时,d+会吧控制权交出去。由于d+后面已经没有正则表达式了,所以,整个正则表达式宣告匹 配完成,其结果就是 cfc456, 其中第一组结果是456。亲爱的同学,您明白刚刚的题目的结果,为什么是456了吗?

—————————————————————————————————————————-

当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。以这个表达式为例:a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。这被称为贪婪匹配。

有时,我们更需要懒惰匹配,也就是匹配尽可能少的字符。前面给出的限定符都可以被转化为懒惰匹配模式,只要在它后面加上一个问号?。这样.*?就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复。现在看看懒惰版的例子吧:

a.*?b匹配最短的,以a开始,以b结束的字符串。如果把它应用于aabab的话,它会匹配aab(第一到第三个字符)ab(第四到第五个字符)

发布日期:
分类:Mysql

发表评论

邮箱地址不会被公开。 必填项已用*标注