根据Python3 Regex documentation:
{m,n}?
使结果RE匹配m个到n个重复 RE之前,尝试匹配尽可能少的重复。这个 是前一个限定词的非贪婪版本。例如,在 6个字符的字符串'aaaaaa',a {3,5}将匹配5个'a'字符, 而{3,5}?只能匹配3个字符。
但是,这似乎与以下实验相矛盾:
import re
regex = re.compile('(abc|d|abcde){1,2}?(e|f)')
regex.match('abcdef')
...匹配“ abcde”。这必然涉及(abc | d | abcde)的 2 个重复,即'abc'和'd'。但是,有一个替代匹配候选者仅涉及(abc | d | abcde)的 1 重复,即“ abcde”。
我误读了文档,还是{m,n}?实际减少了匹配的字符数(或其他目的),而不是重复的次数?
答案 0 :(得分:6)
{m,n}?
尝试匹配的次数越少越好,但是它不会进入abc|d|abcde
并改变|
的行为。 |
仍然会首先尝试使用左选项。
(abc|d|abcde){1,2}?
尝试匹配一次(abc|d|abcde)
,然后成功匹配abc
。然后,正则表达式引擎继续处理其余的模式,并尝试匹配(e|f)
,但失败。它回溯并尝试匹配abc|d|abcde
的另一个重复,并匹配d
。它继续继续到(e|f)
并成功匹配e
。
也许您希望回溯会为第一个(abc|d|abcde)
尝试一个不同的选项,然后再尝试第二个(abc|d|abcde)
。它不会那样做。最终,它将尝试这样做,但是首先尝试为{1,2}?
进行更多匹配。
答案 1 :(得分:4)
它不会强制执行最小重复次数,只是允许使其匹配更少的次数。
当您有多个可以匹配的替代项时,正则表达式引擎将以不同的方式处理问题。一些人“渴望”并使用第一个匹配替代项,另一些人使用“最长匹配”规则。显然,Python很渴望。因此,(abc|d|abcde)
将匹配abc
而不是abcde
,然后下一个重复将匹配e
。它不会回溯,看看是否有重复次数更少的结果。
解决方案是将更长的替代品放在首位。更改为
regex = re.compile('(abcde|abc|d){1,2}?(e|f)')
答案 2 :(得分:2)
正则表达式不会评估所有个可能的选项,而是选择最小的选项-如果提供了它发现的第一个选项:
import re regex = re.compile('(abc|def|gh|abcde|fghi){2,3}?(i|j)') rex.match('abcdefghij')
{2,3}的第一个匹配项是abc|def|gh
(从左到右)。
如果对样式进行重新排序,则会得到所需的内容:
import re
rex = re.compile('(abcde|fghi|abc|def|gh){2,3}?(i|j)')
print(rex.match('abcdefghij').group())
输出:
abcdefghij
答案 3 :(得分:1)
nongreedy修饰符可调整正则表达式引擎的 preference 。通常,使用贪婪匹配时,引擎会优先选择最长的最左侧匹配。如果使用小气(非贪婪)匹配,则由小气修饰符控制的匹配将优先选择最短的最左侧匹配。
请注意,引擎仍会尽最大努力寻找匹配项。如果较长的表达式将使引擎返回匹配项,而较短的表达式则不允许,则引擎将选择允许其返回匹配项的匹配项。
考虑回溯可能对您有所帮助。对于贪婪的匹配,引擎将从最大重复成功的假设开始,然后,如果失败,则回溯并尝试连续进行更短的匹配,直到找到匹配或搜索空间耗尽。对于小匹配,首选假设是最短的匹配,而回溯将尝试连续增加重复次数。
您(不清楚的)示例可能绊倒的是,交替指定了回溯的显式顺序。引擎将从替代方案中的第一个模式开始探索匹配,只有在找到匹配项之前搜索空间用尽的情况下,才尝试尝试其他替代方案。
答案 4 :(得分:1)
该组中的alternation从左侧开始匹配,并具有{1,2}?
的非贪婪量词,该量词根据需要匹配并应用于该组。 Python不会尝试找到轮换中最长的匹配项but the first match。
当匹配开始时,引擎首先找到abc
,然后尝试匹配e
或f
,这不匹配,因为{后面紧跟着d
{1}}。
但是由于量词为abc
,因此第一组还有一个可供选择的选择,而回溯则可以再次找到匹配项。它不能匹配{1,2}?
,但是可以匹配abc
。然后,它尝试再次匹配d
或e
,在此位置它可以匹配f