为什么这个正则表达式匹配给出这个结果?
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']
通过将正则表达式递归地应用于所有这些子匹配,您将获得所有可能的匹配(数量相当多)。
对于元字符+
,模式必须至少出现一次。在尝试匹配此字符串中的 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']
通过将正则表达式递归地应用于所有这些子匹配,您将获得所有可能的匹配(数量相当多)。