Skip to main content
 首页 » 编程设计

python之在正则表达式中替代匹配 "|"与 .* 的行为

2024年08月19日43artech

我很少用 |连同 .* 之前。但是今天当我同时使用它们时,我发现一些结果真的很困惑。我使用的表达式如下(在 python 中):

>>> s = "abcdefg" 
>>> re.findall(r"((a.*?c)|(.*g))",s) 
[('abc',''),('','defg')] 

第一次捕获的结果是好的,但是第二次捕获出乎我的意料,因为我预计第二次捕获是“abcdefg”(整个字符串)。

然后我颠倒这两种选择:

>>> re.findall(r"(.*?g)|(a.*?c)",s) 
[('abcdefg', '')] 

似乎正则表达式引擎只读取一次字符串 - 当整个字符串在第一个备选方案中被读取时,正则表达式引擎将停止并且不再检查第二个备选方案。但是,对于第一种情况,正则引擎在处理完第一种备选方案后,只读取了“a”到“c”,字符串中还剩下“d”到“g”,匹配“.*? g"在第二个选项中。我做对了吗?更重要的是,对于带有替代项的表达式,正则表达式引擎将首先检查第一个替代项,如果它与字符串匹配,则永远不会检查第二个替代项。是否正确?

此外,如果我想像第一种情况那样同时获得“abc”和“abcdefg”或“abc”和“bcde”(两个结果重叠),我应该使用什么表达式?

非常感谢!

请您参考如下方法:

您不能从正则表达式中的相同位置开始两个匹配项(唯一的正则表达式风格是 Perl6)。

在re.findall(r"((a.*?c)|(.*g))",s)中,re.findall会抓取所有字符串中不重叠匹配,并且由于第一个从头开始,以c结束,下一个只能在c之后,在内找到defg.

(.*?g)|(a.*?c) 正则表达式匹配 abcdefg 因为正则表达式引擎从左到右解析字符串,而 .*? 将尽可能少地获取任何 0+ 个字符,但最多到第一个 g。由于 g 是最后一个字符,它将匹配并将整个字符串捕获到组 1 中。

要获取 abc 和 abcdefg,您可以使用,比如说

 (a.*?c)?.*g 

参见 regex demo

Python demo :

import re 
rx = r"(a.*?c)?.*g" 
s = "abcdefg" 
m = re.search(rx, s) 
if m: 
    print(m.group(0)) # => abcdefg 
    print(m.group(1)) # => abc 

这可能不是您真正想要的,但它应该给您一个提示:您匹配较大的部分,并捕获字符串的子部分。