Python 正则表达式中的 *?

4 投票
3 回答
2042 浏览
提问于 2025-04-17 13:40

这个Python的正则表达式匹配什么呢?

.*?[^\\]\n

我有点搞不懂,为什么.后面会跟着*?这两个符号。

3 个回答

5

打开Python re模块的文档,搜索*?,我们可以找到以下内容:

*?+???

这几个符号*+?都是贪婪的,它们会尽可能多地匹配文本。有时候,这种行为并不是我们想要的。例如,如果我们用正则表达式<.*>去匹配<H1>title</H1>,它会匹配整个字符串,而不仅仅是<H1>。在这些符号后面加上?,就可以让它们以非贪婪的方式匹配,也就是说,它们会尽量少匹配字符。比如在之前的表达式中使用.*?,就只会匹配到<H1>

6

. 表示一个通配符。它可以匹配任何东西,除了换行符 \n,除非你使用了合适的标志。

* 表示前面的东西可以出现0次或多次。

? 表示前面的量词是懒惰的。它会在找到第一个匹配项后就停止搜索。

6

*的意思是“尽可能多地匹配前面的元素(可以是零次或多次)”。

*?的意思是“尽可能少地匹配前面的元素(可以是零次或多次)”。

其他回答已经讨论过这个问题,但他们没有提到它如何改变正则表达式。如果提供了re.DOTALL这个标志,会有很大的不同,因为启用后.会匹配换行符。所以.*[^\\]\n会从字符串的开头匹配到最后一个没有被反斜杠前缀的换行符(这样会匹配多行)。

如果没有提供re.DOTALL标志,差别就比较微妙了,[^\\]会匹配除了反斜杠以外的所有字符,包括换行符。考虑以下例子:

>>> import re
>>> s = "foo\n\nbar"
>>> re.findall(r'.*?[^\\]\n', s)
['foo\n']
>>> re.findall(r'.*[^\\]\n', s)
['foo\n\n']

这个正则表达式的目的是找到不以反斜杠结尾的非空行,但如果你用.*代替.*?,那么在非空行后面有空行的情况下,你会多匹配一个\n

这是因为.*?只会匹配fo[^\\]会匹配第二个o,而\n会在第一行的末尾匹配。然而.*会匹配foo[^\\]会匹配\n来结束第一行,接下来的\n会匹配,因为第二行是空的。

撰写回答