re.findall() 的模式行为,后跟一个捕获组,后跟一个量词 [duplicate]

re.findall()'s behavior for patterns with a single capturing group followed by a quantifier [duplicate]

提问人:MojavePatroller 提问时间:11/1/2023 最后编辑:InSyncMojavePatroller 更新时间:11/1/2023 访问量:72

问:

如果模式具有单个量化捕获组,则 re.findall() 似乎不会返回实际匹配项。

例如:

p1 = r"(apple)*"
t1 = "appleappleapple"

re.findall(p1, t1) # returns "['apple', '']" 

而在

[i.group() for i in re.finditer(p1, t1)]

产生完全匹配,即['appleappleapple', '']

另一件让我感到困惑的事情是这种行为:

t2 = "appleapplebananaapplebanana"

re.findall(p1, t2) will return "['apple', '', '', '', '', '', '', 'apple', '', '', '', '', '', '', '']"

这些额外的空字符串究竟是从哪里来的?为什么 findall() 会在输入字符串末尾之前捕获它们?

正则表达式 python-re

评论


答:

-1赞 Deepak Gupta 11/1/2023 #1

让我们首先尝试了解 * 和 () 是如何工作的。此正则表达式尝试将模式与“零个或多个前一个字符或组”匹配。

p1 = r"(banana)*"
t1 = "apple"
res = re.findall(p1, t1) # returns ['', '', '', '', '', '']
print(len(t1)) # returns 5 
print(len(res)) #returns 6 

现在,在从 len 返回后,我们知道为什么这些空白会出现,它试图与每个“前面的角色”和组匹配。这就是为什么它返回 6 个空字符串表示不匹配(5 个字符 + 1 个组)。

现在我们如何删除这些空字符串。好吧,我已经稍微玩了一下这个模式,这就是我发现的。删除 (.

p1 = r"apple*"
t1 = "appleappleapple"
res = re.findall(p1, t1) #returns ['apple', 'apple', 'apple']

也使用相同的模式

[i.group() for i in re.finditer(p1, t1)] # returns ['apple', 'apple', 'apple']

t2 = "appleapplebananaapplebanana"
re.findall(p1, t2) #returns ['apple', 'apple', 'apple']
0赞 Chirag Mehta 11/1/2023 #2

我认为@Deepak的回答并没有完全解决这个问题。

让我们检查第一个代码片段:

p1 = r"(apple)*"
t1 = "appleappleapple"

re.findall(p1, t1)  # returns "['apple', '']"

让我们澄清一下我们的期望。我原以为上述代码片段的输出是 ['appleappleapple', '']。这是因为应该贪婪地匹配到最后,并且由于它只提供非重叠匹配,因此唯一的其他匹配应该是空字符串。findall

但是,为什么输出不同?

文档中所述,如果字符串中存在一个或多个组,则返回的是组。这就是为什么你获得苹果作为匹配而不是苹果苹果的原因。

现在,关于第三个片段,我相信迪帕克的回答确实解决了这个问题。不过,为了完整起见,我也会在这里提到它:

t2 = "appleapplebananaapplebanana"

re.findall(p1, t2) will return "['apple', '', '', '', '', '', '', 'apple', '', '', '', '', '', '', '']"

由于您使用了 ,它将匹配该组的 0 次或多次出现。这就是获取所有这些空字符串的原因。*