【问题标题】:Python re.findall() is not working as expectedPython re.findall() 没有按预期工作
【发布时间】:2012-10-21 15:50:25
【问题描述】:

我有代码:

import re
sequence="aabbaa"
rexp=re.compile("(aa|bb)+")
rexp.findall(sequence)

这将返回['aa']

如果我们有

import re
sequence="aabbaa"
rexp=re.compile("(aa|cc)+")
rexp.findall(sequence)

我们得到['aa','aa']

为什么有区别,为什么(对于第一个)我们没有得到['aa','bb','aa']

谢谢!

【问题讨论】:

    标签: python regex


    【解决方案1】:

    不想要的行为归结为您制定正则表达式的方式:

    rexp=re.compile("(aa|bb)+")
    

    括号(aa|bb) 组成一个组。

    如果我们查看docs of findall,我们会看到:

    返回字符串中所有不重叠的模式匹配,作为一个列表 字符串。从左到右扫描字符串,并返回匹配项 按照找到的顺序。 如果一个或多个组出现在模式中返回组列表;这将是一个元组列表,如果模式 有多个组。结果中包含空匹配项 除非他们触及另一场比赛的开始。**

    当你组成一个组时,它首先计算 aa,然后是 bb,然后是 aa(因为 + 量词)。所以这个组最后持有aa。而findall在列表['aa']中返回这个值(因为整个表达式只有一个匹配aabbaa,所以列表中只有一个元素aa保存在组中)。

    根据您提供的代码,您似乎想要这样做:

    >>> rexp=re.compile("(?:aa|bb)+")
    >>> rexp.findall(sequence)
    ['aabbaa']
    

    (?: ...) 不创建任何组,因此findall 返回整个表达式的匹配项。

    在您的问题结束时,您会显示所需的输出。这可以通过查找aabb 来实现。不需要量词(+*)。就按照 Inbar Rose 的回答来做吧:

    >>> rexp=re.compile("aa|bb")
    >>> rexp.findall(sequence)
    ['aa', 'bb', 'aa']
    

    【讨论】:

    • 我试着用一种非常复杂的方式来表达这个,很好地解释清楚。 :) 和 +1 用于引用文档。 :)
    【解决方案2】:

    让我解释一下你在做什么:

    regex = re.compile("(aa|bb)+")
    

    您正在创建一个正则表达式,它将查找 aabb,然后尝试查找是否还有更多 aabb,然后它将继续寻找 aa 或 @ 987654327@ 直到找不到。因为您希望您的捕获组仅返回 aabb,所以您只能获得最后一个捕获/找到的组。

    然而,如果你有一个这样的字符串:aaxaabbxaa,你会得到aa,bb,aa,因为你首先查看字符串并找到aa,然后再寻找更多,却只找到x,所以你有1组。然后你找到另一个aa,然后你找到一个bb,然后是一个x,所以你停下来,你有了第二组bb。然后你找到另一个aa。所以你的最终结果是aa,bb,aa

    我希望这能解释你在做什么。正如预期的那样。要获得aabb 的任何组,您需要删除+,它告诉正则表达式在返回匹配之前寻找多个组。并且只需让正则表达式返回aabb 的每个匹配项...

    所以你的正则表达式应该是:

    regex = re.compile("(aa|bb)")
    

    干杯。

    【讨论】:

    • 优秀。谢谢你。我根本想不通。
    • 不相关:当您标记答案而不是“非常低质量”时,您能否将它们标记为“不是答案”?在处理这些标志时,它对我们有很大帮助。谢谢!
    【解决方案3】:

    你的模式

    rexp=re.compile("(aa|bb)+")
    

    匹配整个字符串 aabbaa。澄清一下看看这个

    >>> re.match(re.compile("(aa|bb)+"),"aabbaa").group(0)
    'aabbaa'
    

    也没有其他子字符串可以匹配

    >>> re.match(re.compile("(aa|bb)+"),"aabbaa").group(1)
    'aa'
    

    所以 findall 将只返回一个子字符串

    >>> re.findall(re.compile("(aa|bb)+"),"aabbaa")
    ['aa']
    >>> 
    

    【讨论】:

      【解决方案4】:

      我不明白你为什么使用 + - 这意味着出现 0 或 1 次,通常用于查找可选包含子字符串的字符串。

      >>> re.findall(r'(aa|bb)', 'aabbaa')
      ['aa', 'bb', 'aa']
      

      按预期工作

      【讨论】:

      • No + 不代表 0 或 1,应该是 ?+ 表示 1 个或多个。
      • 你的逻辑是错误的,但你的答案是正确的。 + 表示 one or more matches? 表示 matches one or no matches 。我不知道您所说的“通常在您想要查找带有可选包含子字符串的字符串时使用”是什么意思。但它具有误导性。答案是,如果您想捕获具有可选值的组,您可以按照上面的回答进行操作。在正则表达式中包含+ 会导致它寻找多个捕获组并仅返回他捕获的最后一个。如果他们是并发/互相跟随。
      • 好的,我来了。有一段时间没有使用 RE - 对我的目的来说太重了。
      猜你喜欢
      • 1970-01-01
      • 2012-05-09
      • 2014-02-26
      • 1970-01-01
      • 1970-01-01
      • 2011-08-27
      • 2014-10-11
      • 1970-01-01
      相关资源
      最近更新 更多