我很少使用|与*之前一起。但今天当我同时使用它们时,我发现一些结果确实令人困惑。我使用的表达式如下(在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" (两个结果重叠)就像第一种情况一样,我应该使用什么表达式?
非常感谢你!
答案 0 :(得分:2)
你不能从正则表达式中的相同位置开始有两个匹配(唯一的正则表达式就是Perl6)。
在re.findall(r"((a.*?c)|(.*g))",s)
中,re.findall
会抓取字符串中所有非重叠的匹配项,并且由于第一个匹配项从开头开始,以c
结尾,下一个匹配项只能是在c
之后defg
内找到。
(.*?g)|(a.*?c)
正则表达式与abcdefg
匹配,因为正则表达式引擎从左到右解析字符串,而.*?
将尽可能少地获取任何0+字符,但直到第一个字符{ {1}}。由于g
是最后一个字符,它将匹配并将整个字符串捕获到组1中。
要获得g
和abc
,您可以使用
abcdefg
请参阅regex demo
(a.*?c)?.*g
它可能不是你想要的,但它应该给你一个提示:你匹配较大的部分,并捕获字符串的子部分。
答案 1 :(得分:1)
重新阅读re.findall
方法的文档。
findall
"返回[s]字符串中pattern的所有非重叠匹配,作为字符串列表。字符串从左向右扫描,匹配按查找顺序返回。"
具体来说,非重叠匹配,从左到右。因此,如果您有一个字符串abcdefg
并且一个模式将匹配abc
,那么任何其他模式必须(1)不重叠; (2)进一步向右。
根据说明,匹配abc
和defg
非常有效。匹配abc
和abcdefg
甚至abc
和cdefg
是一个错误,因为它们会重叠。