为什么这个正则表达式匹配给出这个结果?

Why is this regular expression matching giving this result?

对于元字符+,模式必须至少出现一次。在尝试匹配此字符串中的 a[ab]+ 时:abbaaabbbbaaaaa 使用 python 的 re.findall(),我希望它 return 从第一个字母开始的所有可能匹配a['ab', 'abb', 'abba', 'abbaaa', ... etc] 一样,直到到达整个字符串(这也是一个匹配项)。此外,我认为它也适用于字符串中的每个 a 而不仅仅是第一个,所以我想匹配的结果会比这个更多。

这是我使用的代码:

import re

string = 'abbaaabbbbaaaaa'
matches = re.findall('a[ab]+', string)
for match in matches:
    print(match)

然而,结果只是abbaaabbbbaaaaa(整个字符串)。那我理解错了什么?

方括号是一个字符class,意思是匹配这些字符中的任意一个

因此,[ab]+匹配一个或多个连续为a或b的字符。您的模式将通过一次匹配吞噬整个字符串。

您可能想要的是:

re.findall('a(?:ab)+', string)

请注意 (?:...) 是一个非捕获组。它与 (...) 在此模式中的工作方式相同,但效率更高,因为它不保存子组(您不需要)。

a[ab]+ 将匹配单个字符串(假设它完全匹配)。整个字符串 abbaaabbbbaaaaa 匹配该正则表达式,因此您得到一个匹配项:整个字符串。它不会给你每一个可能匹配的小片段。

换句话说,a[ab]"consumes"各匹配一个字符。也就是说,匹配的字符是"used up,",程序移动到下一个字符。通常,这就是您想要的:您想查看整个字符串是否匹配,或者有多少匹配,而不是查找构成更大匹配的所有零散部分。

正则表达式只能找到非重叠的匹配项(除非你使用像 positive lookahead assertions with capturing groups 这样的特殊技巧)。

此外,你的+quantifier默认是贪心的,匹配尽可能多的字符。如果你给它加一个 ? ,它就会变得懒惰,所以它会在第一个可能的点停止。这为您提供了一个非重叠匹配列表,但这也不是您所期望的:

['ab', 'aa', 'ab', 'aa', 'aa']
# as in ABbAAABbbbAAAAa

如果你这样做

matches = re.findall('(?=(a[ab]+))', string)

您从字符串中每个可能的起点获得所有匹配项:

['abbaaabbbbaaaaa',
 'aaabbbbaaaaa',
 'aabbbbaaaaa',
 'abbbbaaaaa',
 'aaaaa',
 'aaaa',
 'aaa',
 'aa']

通过将正则表达式递归地应用于所有这些子匹配,您将获得所有可能的匹配(数量相当多)。