Python 正则表达式中的 *?
这个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
会匹配,因为第二行是空的。