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

eal*_*nso 9 python regex capture optional

import re
str='abc defg'
m1 = re.match(".*(def)?",str)
m2 = re.match(".*(def)",str)
print (m1.group(1),m2.group(1))
Run Code Online (Sandbox Code Playgroud)

以上的输出是:

(没有,'def')

到底是怎么回事?即使使用非贪婪的重复运算符,(def)?也不会匹配可选的捕获组.

Ilm*_*nen 13

下面是当正则表达式引擎尝试匹配会发生什么.*(def)反对abc defg:

  • 首先,引擎开始尝试匹配字符串开头的正则表达式.
  • 贪婪的子模式.*最初尝试匹配尽可能多的次数,匹配整个字符串.
  • 由于这会导致匹配的其余部分失败,因此正则表达式引擎会回溯,直到找到匹配的方式(def),这.*仅在匹配时发生abc .

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

  • 首先,正则表达式引擎再次从字符串的开头开始.
  • 接下来,它再次尝试匹配.*尽可能多的匹配整个字符串.
  • 但是那时候,因为正则表达式的所有其余部分都是可选的,所以它找到了整个正则表达式的匹配!由于(def)?是贪婪的,如果可能,引擎更喜欢匹配它,但它不会回溯早期的子模式只是为了看它是否可以.相反,它只是让.*吞噬整个字符串,没有留下任何东西(def)?.

类似的事情发生在.*?(def).*?(def)?:

  • 同样,引擎从字符串的开头开始.
  • ungreedy子模式.*?尝试尽可能地匹配,即根本不匹配.
  • 那时,(def)无法比拟,但(def)?可以.因此,对于(def)正则表达式引擎必须返回并考虑更长的匹配,.*?直到它找到一个允许完整模式匹配,而因为(def)?它不必这样做,所以它不会.

有关更多信息,请参阅Perl正则表达式手册"组合RE部分"部分(与Python的"Perl兼容"正则表达式的行为相匹配).