【问题标题】:Why is this regular expression matching giving this result?为什么这个正则表达式匹配会给出这个结果?
【发布时间】:2015-11-13 06:29:41
【问题描述】:

对于元字符+,模式必须至少出现一次。在尝试匹配此字符串中的a[ab]+ 时:abbaaabbbbaaaaa 使用 python 的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(整个字符串)。那我理解错了什么?

【问题讨论】:

    标签: python regex regex-greedy


    【解决方案1】:

    a[ab]+ 将匹配单个字符串(假设它完全匹配)。整个字符串 abbaaabbbbaaaaa 匹配那个正则表达式,所以你得到一个匹配:整个字符串。它不会给你所有可能匹配的小块。

    换一种说法,a[ab] 的每个匹配“消耗”一个字符。也就是说,匹配的字符被“用完”,程序移动到下一个字符。一般来说,这就是您想要的:您想查看整个字符串是否匹配,或者匹配多少,而不是查找构成更大匹配的所有点点滴滴。

    【讨论】:

      【解决方案2】:

      正则表达式只能找到不重叠的匹配项(除非您使用特殊技巧,例如 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']
      

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

      【讨论】:

        【解决方案3】:

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

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

        你可能想要的是:

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

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

        【讨论】:

          猜你喜欢
          • 2018-08-24
          • 2020-01-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-09-17
          • 1970-01-01
          • 2013-04-19
          相关资源
          最近更新 更多