为什么re.findall('(ab)+',' abab')返回[' ab'] =同时re.findall('(ab) )+?',' abab')返回[' ab',' ab']?

时间:2015-04-03 11:00:37

标签: python regex

我的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如何在这里工作?
为什么???

3 个答案:

答案 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正常工作:

  1. 如果没有捕获组,它会将字符串中的所有匹配项提供给结果列表。
  2. 如果有一个捕获组,它将仅返回捕获组列表。
  3. 如果有多个捕获组,将返回一个元组列表,其中1个元组包含一个匹配的捕获组。
  4. 接下来,只要组重复,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']