Python的re.findall()方法无法按预期工作

14

我有这段代码:

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']

谢谢!

4个回答

11

所述的不良行为归结于您构建正则表达式的方式:

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

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

如果我们查看 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 - Inbar Rose

10

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

regex = re.compile("(aa|bb)+")
你正在创建一个正则表达式,该表达式将查找aabb,然后尝试查找是否有更多的aabb,并且它将继续查找aabb,直到找不到为止。由于你想要你的捕获组只返回aabb,那么你只会得到最后一个被捕获/找到的组。
但是,如果你有这样的字符串:aaxaabbxaa,你将得到aa,bb,aa,因为你首先查看字符串并找到aa,然后查找更多,并且只找到了一个x,所以你有1个组。然后你找到另一个aa,但接着你找到了一个bb,然后是一个x,所以你停止了,并且你有第二个组,即bb。然后你找到了另一个aa。因此,你的最终结果是aa,bb,aa
我希望这解释了你在做什么,而且这也是预期的。要获取任何aabb组,你需要删除+,它是告诉正则表达式在返回匹配之前寻找多个组,并且只让正则表达式返回每个aabb的匹配项...
因此,你的正则表达式应该是:
regex = re.compile("(aa|bb)")

干杯。


太好了,谢谢。我完全想不出来。 - Dale Myers
在标记答案时,可以将它们标记为“不是答案”,而不是“非常低质量”吗?这对我们处理这些标记非常有帮助。谢谢! - casperOne

0

你的模式

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']
>>> 

-1

我不明白为什么您使用+ - 它表示0或1次出现,并且通常用于当您想要查找包含子字符串的可选情况时。

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

按预期工作


2
不,+并不意味着0或1,那应该是?+表示1个或更多。 - halex
你的逻辑有误,但你的答案是正确的。+ 表示 一个或多个匹配, 而 ? 表示 匹配零个或一个. 我不知道你所说的 "通常用于在要查找包含子字符串的可选字符串时" 是什么意思,但这很误导人。答案是,如果你想捕获具有可选值的组,你可以按照你之前的回答进行操作。在正则表达式中包含一个 + 会导致它寻找多个捕获组并仅返回它捕获的最后一个捕获组,如果它们是连续/相互跟随的。 - Inbar Rose
好的,我明白了。我已经有一段时间没有使用正则表达式了,对于我的目的来说太重了。 - volcano

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接