问题
使用正则表达式匹配字符串时,返回的是最长匹配,需要修改它变成查找最短的匹配。
解决方案
这个问题,一般出现在需要匹配一对分隔符之间的文本时,比如:
import re
text1 = 'Computer says "no."'
text2 = 'Computer says "no." Phone says "yes."'
str_pat = re.compile(r'".*"')
print(str_pat.findall(text1))
print(str_pat.findall(text2))
['"no."']
['"no." Phone says "yes."']
在例子(2)中,需求是匹配被双引号包含的文本,但是在正则表达式中*
操作符是贪婪的,匹配操作会查找最长的可能匹配,返回的结果并不是我们想要的。
为了修正这个问题,可以在*
操作符后面加上?
修饰符,比如:
str_pat1 = re.compile(r'".*?"')
print(str_pat1.findall(text2))
['"no."', '"yes."']
这样就使得匹配变成非贪婪模式,从而得到最短的匹配,也就是我们想要的结果。
讨论
在正则表达式中,点(.)
字符匹配除了换行外的任何字符。
如果将点(.)
放在开始与结束符(比如引号)之间,匹配操作会查找符合模式的最长可能匹配,会导致很多中间的被开始与结束符包含的文本被忽略掉,并最终被包含在匹配结果字符串中返回。