我的python版本是2.7.6
我知道+?
是+
的非贪婪版本
以便re.findall('(ab)+?', 'abab')
匹配尽可能少ab
结果['ab', 'ab']
因此有意义。
但是当谈到贪婪的版本匹配re.findall('(ab)+', 'abab')
时,它让我很困惑
我认为贪婪的版本应该尽可能多地匹配ab
因此我得到['abab']
作为结果
但我改为['ab']
了!
在re.findall()的帮助信息中,它说:
Return a list of all non-overlapping matches in the string.
If one or more groups are present in the pattern, return a
list of groups; this will be a list of tuples if the pattern
has more than one group.
Empty matches are included in the result.
我在这里得到了两个组,整个RE的默认group0
和我指定的(ab)
为group1
。
所以我做了以下调查:
In [21]: ng = re.search('(ab)+?', 'abab')
In [22]: g = re.search('(ab)+', 'abab')
In [23]: ng.group(0)
Out[23]: 'ab'
In [24]: ng.group(1)
Out[24]: 'ab'
In [25]: g.group(0)
Out[25]: 'abab'
In [26]: g.group(1)
Out[26]: 'ab'
很明显,re
模块将'abab'
与group0匹配,'ab'
与group1匹配,以进行贪婪搜索。
但是,在进行['ab']
操作时,为什么我会['abab', 'ab']
而不是findall()
?
因为'abab'
包含ab
所以它们是重叠的,findall()
只返回这种情况下的最后一场比赛?
有了这个问题,我做了以下测试:
In [30]: g = re.findall('[A-z](ab)+', 'ababdab')
In [31]: g
Out[31]: ['ab', 'ab']
In [32]: dg = re.search('[A-z](ab)+', 'ababdab')
In [33]: dg.groups()
Out[33]: ('ab',)
In [34]: dg.group()
Out[34]: 'bab'
现在我完全忘记了。
findall如何在这里工作?
为什么???
答案 0 :(得分:2)
这里有一个微妙之处 - 在杰瑞的回答中提到,但没有说清楚。
您希望re.findall('(ab)+', 'abab')
告诉您两者隐含的"组0"对于整个正则表达式匹配的内容,和" group 1"括号。 这不是它的工作方式。如果有捕获括号,findall
列表仅包含捕获括号的组。观察:
>>> re.findall('(?:ab)+', 'abab') # no capture, reports group 0
['abab']
>>> re.findall('(ab)+', 'abab') # one capture, reports _only_ group 1
['ab']
>>> re.findall('((ab)+)', 'abab') # two captures, reports both groups 1 and 2
[('abab', 'ab')] # (but still not group 0)
文档可以更清楚地了解这一点。它假设你理解"组0"并不算作一个群体。但这就是RE库已经运作了几十年的过程。
答案 1 :(得分:1)
findall
正常工作:
接下来,只要组重复,MatchObject就会返回最后捕获的组。它在docs中提到:
如果一个组多次匹配,则只能访问最后一个匹配:
>>> >>> m = re.match(r"(..)+", "a1b2c3") # Matches 3 times. >>> m.group(1) # Returns only the last match. 'c3'
因此两种现象的组合会给出您正在经历的结果。
答案 2 :(得分:-1)
看看:
In [13]: re.findall('(ab)', 'ababab')
Out[13]: ['ab', 'ab', 'ab']
In [14]: re.findall('(ab)+?', 'ababab')
Out[14]: ['ab', 'ab', 'ab']
In [15]: re.findall('(ab)+', 'ababab')
Out[15]: ['ab']
In[13]
相当于In[14]
。两种模式都匹配每个ab
组。但是,In[15]
将匹配所有ab
个连续重复,无论其数量如何。
[A-z](ab)+
模式意味着您希望以字母ab
开头的所有[A-z]
个连续重复。在ababdab
中与bab
匹配的第一个组是b
:它以[Az]中的ab
开头,然后有一个以{{{}结尾的d
组1}},它启动下一个匹配组。
In [20]: re.findall('[A-z](ab)+', 'XababXabXab')
Out[20]: ['ab', 'ab', 'ab']