正则表达式量词与贪婪的使用详解

0.写在前面

上一篇文章中,我们学习了正则的一些基础元字符,相信大家都已经忘却的差不多了,可以点击上面的链接再温习下。

今天我们一起来学习下正则中量词的三种匹配模式,贪婪模式、非贪婪模式、独占模式,这些模式会改变正则中量词的匹配行为,是每次贪婪的匹配到更多呢,还是不贪婪见好就收呢,如果不了解这些,我们写出的正则很可能是错误的,甚至会引发严重的线上性能问题。

1.量词

本篇文章所讲的内容和量词关系比较密切,先回顾下:

量词

我们还可以用 {m,n} 的方式来表示 * + ? 这3种元字符:

元字符 同义表示方法 示例
*   {0,}   ab*
可以匹配
a 或者 abb
 
+   {1,}   ab+
可以匹配
ab 或者 abb
但不能匹配 a
 
?   {0,1}   ab?
可以匹配 a 或者 ab
但不能匹配 abb
 

2.贪婪模式前传

在正则中,表示次数的量词默认是贪婪的,在贪婪模式下,会尽可能最大长度的去匹配目标字符串,我们用正则 a+a* 来匹配字符串 aaabb 测试一下。

2.1 使用 a+ 进行匹配

可以看到只匹配到了1个结果 aaa

a+匹配

对应的 Python 代码如下:

import re print(re.findall(r'a+', 'aaabb')) 输出:['aaa']

2.2 使用 a* 进行匹配

可以看到匹配到了4个结果,其中还有3个是空字符串

a*匹配.jpg

对应的 Python 代码如下:

import re print(re.findall(r'a*', 'aaabb')) 输出:['aaa', '', '', '']

为什么会匹配到空字符串呢?因为星号(*)代表匹配0到多次,匹配0次就是空字符串,那前面还有个 aaa 呢,为什么 aaa 之间的空字符串没有被匹配到?

这就引入到了我们今天要讲的,贪婪模式与非贪婪模式,从字面上很好理解,贪婪模式就是尽可能多的匹配,非贪婪模式就是尽可能少的匹配。

3.贪婪模式

一起来分析下上面正则 a* 的匹配过程:

字符串 a a a b b 空字符串
下标   0   1   2   3   4   5  

匹配 开始 结束 说明 匹配内容
第一次   0   3   到第一个字母b发现不匹配,输出aaa   aaa  
第二次   3   3   匹配剩下的bb,发现匹配不上,输出空字符串   空字符串  
第三次   4   4   匹配剩下的b,发现匹配不上,输出空字符串   空字符串  
第四次   5   5   匹配剩下的空字符串,输出空字符串   空字符串  

a* 在匹配字符串 aaabb 时,会尽可能多的把前面的 a 都匹配上,直到第一个字母 b 不满足要求为止,匹配上3个 a,后面每次匹配的都是空字符串。

看到这里,相信你已经对贪婪模式有了更深的印象,贪婪模式的特点就是尽可能进行最大长度匹配,就是有多少要多少,下面我们在一起来看下与它完全相反的匹配模式。

4.非贪婪模式

上面讲完了贪婪模式,贪婪模式是尽可能最大长度匹配,非贪婪模式就是尽可能最小长度匹配,在量词的后面加一个问号(?),就成了非贪婪模式,比如 a*?

非贪婪匹配

对应的 Python 代码如下:

import re // 贪婪匹配 print(re.findall(r'a*', 'aaabb')) 输出:['aaa', '', '', ''] // 非贪婪匹配 print(re.findall(r'a*?', 'aaabb')) 输出:['', 'a', '', 'a', '', 'a', '', '', '']

学完了贪婪模式与非贪婪模式,你可能会问,我什么情况下会用到呢,下面举个栗子感受下:

贪婪匹配例子

非贪婪匹配例子

需求是查找一段字符串中,所有双引号括起来的内容,上面使用贪婪匹配与非贪婪匹配的对比,差别很明显对吧。

5.独占模式

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyfddp.html