Python正则表达式问号运算符不起作用?

11
import re
str='abc defg'
m1 = re.match(".*(def)?",str)
m2 = re.match(".*(def)",str)
print (m1.group(1),m2.group(1))
上面的输出结果是:

(None, 'def')

发生了什么事情?即使使用了非贪婪重复运算符,可选捕获组((def)?)也没有被匹配。
1个回答

15

当正则表达式引擎尝试在字符串abc defg上匹配.*(def)时,会发生以下情况:

  • 首先,引擎从字符串的开头开始尝试匹配正则表达式。
  • 贪婪子模式.*最初尝试尽可能多地匹配,从而匹配整个字符串。
  • 由于这导致其余匹配失败,正则表达式引擎回溯直到找到匹配(def)的方法,即当.*仅匹配abc 时发生。

然而,如果我们将正则表达式更改为.*(def)?,则会发生以下情况:

  • 首先,正则表达式引擎再次从字符串的开头开始。
  • 接下来,它尝试尽可能多地匹配.*,从而匹配整个字符串。
  • 但此时,由于其余所有正则表达式都是可选的,它已经找到了整个正则表达式的匹配项! 由于(def)?是贪婪的,引擎虽然希望能够匹配它,但它不会回溯之前的子模式,只是让.*吞噬整个字符串,没有留下任何内容给(def)?

对于.*?(def).*?(def)?也发生类似的情况:

  • 同样,引擎从字符串的开头开始。
  • 非贪婪子模式.*?尝试最少地匹配,即根本不匹配。
  • 此时,(def)无法匹配,但(def)?可以。 因此,对于(def),正则表达式引擎必须返回并考虑更长的.*?匹配,直到找到一个能够使全模式匹配的匹配项,而对于(def)?,它不必这样做,因此它不会这样做。

有关更多信息,请参见Perl正则表达式手册中的“组合RE片段”部分(与Python的“ Perl兼容”正则表达式的行为相匹配)。


非常抱歉直到现在才接受您的答案。我是论坛的新手,对事情不太确定。感谢您提供的全面解释。实际上,我以前写过一个正则表达式引擎,所以本应该能够解决这个问题。 - ealfonso

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接