在 Python 正则表达式中,我遇到了这个奇异的问题。你能说明re.findall('(ab|cd)', string)和之间的区别re.findall('(ab|cd)+', string)吗?
import re
string = 'abcdla'
result = re.findall('(ab|cd)', string)
result2 = re.findall('(ab|cd)+', string)
print(result)
print(result2)
Run Code Online (Sandbox Code Playgroud)
实际输出为:
['ab', 'cd']
['cd']
Run Code Online (Sandbox Code Playgroud)
我很困惑为什么第二个结果也不包含'ab'?
Sha*_*k V 16
+是匹配一次或多次的重复量词。在正则表达式中(ab|cd)+,您使用 +重复捕获组 (ab|cd)。这只会捕获最后一次迭代。
您可以对这种行为进行如下推理:
假设您的字符串是abcdla,正则表达式是(ab|cd)+. 正则表达式引擎将在位置 0 和 1 之间找到组的匹配项ab并退出捕获组。然后它看到+量词,因此尝试再次捕获该组并将cd在位置 2 和 3 之间捕获。
如果要捕获所有迭代,则应捕获重复组,而不是使用((ab|cd)+)which 匹配abcd和cd。您可以使内部组不被捕获,因为我们不关心内部组匹配与((?:ab|cd)+)哪些匹配abcd
https://www.regular-expressions.info/captureall.html
从文档中,
假设您想匹配像
!abc!or 之类的标签!123!。只有这两个是可能的,并且您想捕获abcor123以找出您获得的标签。这很容易:!(abc|123)!会做的伎俩。现在假设标签可以包含多个
abcand 序列123,例如!abc123!or!123abcabc!。快速简便的解决方案是!(abc|123)+!。这个正则表达式确实会匹配这些标签。但是,它不再满足我们将标签的标签捕获到捕获组中的要求。当此正则表达式匹配时!abc123!,捕获组仅存储123. 当它匹配时!123abcabc!,它只存储abc。
我不知道这是否会使事情更清楚,但让我们尝试以简单的方式想象引擎盖下发生的事情,我们将使用 match 总结发生的事情
# group(0) return the matched string the captured groups are returned in groups or you can access them
# using group(1), group(2)....... in your case there is only one group, one group will capture only
# one part so when you do this
string = 'abcdla'
print(re.match('(ab|cd)', string).group(0)) # only 'ab' is matched and the group will capture 'ab'
print(re.match('(ab|cd)+', string).group(0)) # this will match 'abcd' the group will capture only this part 'cd' the last iteration
Run Code Online (Sandbox Code Playgroud)
findall匹配并同时使用字符串让我们想象一下这个 REGEX 会发生什么'(ab|cd)':
'abcdabla' ---> 1: match: 'ab' | capture : ab | left to process: 'cdabla'
'cdabla' ---> 2: match: 'cd' | capture : cd | left to process: 'abla'
'abla' ---> 3: match: 'ab' | capture : ab | left to process: 'la'
'la' ---> 4: match: '' | capture : None | left to process: ''
--- final : result captured ['ab', 'cd', 'ab']
Run Code Online (Sandbox Code Playgroud)
现在同样的事情 '(ab|cd)+'
'abcdabla' ---> 1: match: 'abcdab' | capture : 'ab' | left to process: 'la'
'la' ---> 2: match: '' | capture : None | left to process: ''
---> final result : ['ab']
Run Code Online (Sandbox Code Playgroud)
我希望这能让事情变得更清楚一点。