替代匹配的行为" |"在正则表达式中使用。*

时间:2017-09-13 11:47:42

标签: python regex

我很少使用|与*之前一起。但今天当我同时使用它们时,我发现一些结果确实令人困惑。我使用的表达式如下(在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" (两个结果重叠)就像第一种情况一样,我应该使用什么表达式?

非常感谢你!

2 个答案:

答案 0 :(得分:2)

你不能从正则表达式中的相同位置开始有两个匹配(唯一的正则表达式就是Perl6)。

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

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

要获得gabc,您可以使用

abcdefg

请参阅regex demo

Python demo

 (a.*?c)?.*g

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

答案 1 :(得分:1)

重新阅读re.findall方法的文档。

findall"返回[s]字符串中pattern的所有非重叠匹配,作为字符串列表。字符串从左向右扫描,匹配按查找顺序返回。"

具体来说,非重叠匹配,从左到右。因此,如果您有一个字符串abcdefg并且一个模式将匹配abc,那么任何其他模式必须(1)不重叠; (2)进一步向右。

根据说明,匹配abcdefg非常有效。匹配abcabcdefg甚至abccdefg是一个错误,因为它们会重叠。