为什么 '?','*' 和 '{0,}' 不够贪心?

Why '?','*' and '{0,}' are not greedy enough?

当应用它们的字符之前没有前导字符(空字符串除外)时,您如何证明 ?、{0、} 和 * 的行为?

>>>re.search('b?','abc')
   <re.Match object; span=(0, 0), match=''>

看起来它捕获了一个空字符串,索引为 0,后跟 'b' 出现 0 次,然后停在那里,甚至不用担心字符串的其余部分。在我看来它并不那么贪婪。我希望它能赶上 'b'.

另一方面,下一个工作正常:

>>>re.search('b?c','abc')
   <re.Match object; span=(1, 3), match='bc'>
>>> list(re.finditer('b?', 'abc'))
[<re.Match object; span=(0, 0), match=''>,
 <re.Match object; span=(1, 2), match='b'>,
 <re.Match object; span=(2, 2), match=''>,
 <re.Match object; span=(3, 3), match=''>]

b?有多个匹配项,每个位置一个。 re.search 只有 return 是其中的第一个。它不是return 最长的,它return是第一个。位置1的'b'确实匹配,但是位置0的''的匹配在前。

如果你不想要空字符串 returned 我不会使用 b?。简单搜索 b 不会匹配空字符串。

贪心

当有多个匹配时,贪婪不会优先考虑较长的匹配。相反,它所做的是确定正则表达式引擎在进行匹配时是否会贪婪地吸收尽可能多的字符。例如,如果您使用 b?? 来匹配 non-greedily,它会在位置 1 处添加一个额外的空字符串匹配:

>>> list(re.finditer('b??', 'abc'))
[<re.Match object; span=(0, 0), match=''>,
 <re.Match object; span=(1, 1), match=''>,
 <re.Match object; span=(1, 2), match='b'>,
 <re.Match object; span=(2, 2), match=''>,
 <re.Match object; span=(3, 3), match=''>]

经常出现的 greediness/non-greediness 的一个更有用的示例是尝试匹配开始和结束定界符。例如,假设您尝试将引用的对话框与 ".*":

匹配
>>> re.findall(r'".*"', '"My name is Bond," he said.')
['"My name is Bond,"']

看起来不错。

>>> re.findall(r'".*"', '"My name is Bond," he said. "James Bond."')
['"My name is Bond," he said. "James Bond."']

糟糕。它并没有停在第一个结束引号处。贪婪的 .* 继续前进并消耗额外的未引用和引用的文本。

如果我们将 non-greedy 设为 ".*?",那么它会在看到收盘价后立即停止匹配。它不会让 .* 匹配 ":

>>> re.findall(r'".*?"', '"My name is Bond," he said. "James Bond."')
['"My name is Bond,"', '"James Bond."']