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

时间:2015-11-13 06:29:42

标签: python regex regex-greedy

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

这是我使用的代码:

import re

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

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

3 个答案:

答案 0 :(得分:3)

a[ab]+将匹配单个字符串(假设它完全匹配)。整个字符串abbaaabbbbaaaaa与该正则表达式匹配,因此您获得一个匹配:整个字符串。它没有给你所有可能匹配的小块。

换句话说,a[ab]的每个匹配都会消耗一个字符。也就是说,匹配字符“用完”,程序移动到下一个字符。一般来说,这就是你想要的:你想看看整个字符串是否匹配,或者它是多少匹配,而不是找到构成更大匹配的所有比特。

答案 1 :(得分:3)

正则表达式只能找到不重叠的匹配(除非您使用positive lookahead assertionscapturing groups等特殊技巧。)

此外,您的+ quantifier默认情况下是贪婪的,匹配尽可能多的字符。如果你向它添加?,它会变得懒惰,所以它会在第一个可能的点停止。这会给你一个非重叠匹配的列表,但这并不是你所期望的:

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

如果你这样做

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

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

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

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

答案 2 :(得分:0)

括号是一个字符类,意味着匹配这些字符中的任何一个

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

您可能想要的是:

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

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