对正则表达式贪婪模式与非贪婪模式的理解

演示示例:

#python 3.7
import re
str = ‘a "witch" and her "broom" is one’
a = re.findall(r'"(.*)"',str)
print(a)

贪婪模式(默认):

#python 3.7
import re
str = ‘a "witch" and her "broom" is one’
a = re.findall(r'"(.*)"',str)
print(a)
运行结果:
['witch" and her "broom']

在这里为了直观,我们模拟一下正则引擎

1.第一个查找字符是 " ,正则引擎在第三个位置匹配到了它:

8637116909dacfec548750449e40d084.png

2.之后,引擎尝试匹配正则的剩余部分,第二个字符是 .(点) ,它代表任意字符。引擎匹配到了w:

973d2e2a4062b267947a33e62e186aee.png

3.*代表任意字符重复一次到多次,因此正则引擎匹配到所有字符

65bb97e0f18cb79038c823dd54d33438.png

4.当文本结束后,点的匹配停止了,但仍然有剩余的正则"需要匹配,因此正则引擎开始倒过来回溯,换句话说,就是一个字符一个字符缩减匹配。

5cb5c470e6c1de95e051740d2481518d.png

当匹配缩减后,它开始尝试匹配剩余的正则,但"没有匹配上字符e。

5.因此正则继续缩减.所重复的字符,继续尝试。

d90d606e6cffc3ed02e33999db7f872a.png

边缩减一位,边验证匹配一位

6.正则引擎回溯,一次一次缩减.重复的字符个数,直到剩余的正则都匹配上:

b84699ed26c68400a0bcdbea679ffcfe.png

现在"终于匹配上了。
所以说,在贪婪模式下,正则引擎尽可能多的匹配字符

非贪婪模式:

非贪婪模式和贪婪模式相反,可通过在代表数量的标识符后放置?来开启非贪婪模式,如?、+?甚至是??。
示例:

#python 3.7 
import re str = 'a "witch" and her "broom" is one' 
a = re.findall(r'"(.*?)"',str) 
print(a) 

运行结果: 
['witch', 'broom']

1.第一步和上面类似,引号"被匹配上

8637116909dacfec548750449e40d084.png

2.第二步也一样, '.'被匹配上

973d2e2a4062b267947a33e62e186aee.png

3.下面是二者的重要区别。 正则引擎尝试用最小可能的重复次数来进行匹配,因此在.(点)匹配了w后,它立即尝试"的匹配

f16d9c604e69298475d1fa96b057f8c2.png

可惜没有匹配上,因为i!="

4. .(点)重复更多的字符,再进行尝试

a50a72382b7e32d92f0b817ad44205a1.png

又没匹配上,继续~~

5.下面终于匹配上了

b39c545b6c9886da54d17b484c23aeac.png

6.因为findall匹配全部字符串所以继续往后进行

3359c9db86268a05923726b65da2a0a2.png

同样的道理
所以说,在非贪婪模式下,正则引擎尽可能少的重复匹配字符。

贪婪模式与非贪婪模式的正则引擎匹配的区别在于:

贪婪模式:.(点)先全部进行匹配完,如果还有没有匹配的正则字符,则用未匹配的进行回溯
非贪婪模式:.匹配一个任意字符,下一个接着匹配.后的正则字符 ,如果下一个匹配失败,继续用.匹配,然后在用.后正则字符匹配,直到.后的正则字符匹配成功。

发布了65 篇原创文章 · 获赞 58 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/CliffordR/article/details/104187715