如何制作Python正则表达式以匹配多个模式到同一索引

9

是否可以获取所有重叠匹配项,这些匹配项从相同的索引开始,但来自不同的匹配组?

例如,当我从“ABC”中查找模式“(A)|(AB)”时,正则表达式应返回以下匹配项:

(0,“A”)和(0,“AB”)


实际上这还是个未决问题,我没有很清楚地说明我要寻找什么样的匹配。另一个例子是对于"AABAABA",我想要得到的匹配是(0,['A']),(1,['A','AB']),(3, ['A']),(4, ['A','AB']),(6, ['A'])。 - Mikael Lepistö
这个问答非常有用,因为它回答了两个问题,其中一个被误解了,但仍然很有用。 - n611x007
2个回答

6

关于这个问题的一种可能解释请参见Evpok的回答。另一个解释是你想要从同一位置同时匹配所有模式。在这种情况下,你可以使用前瞻表达式。例如,正则表达式:

(?=(A))(?=(AB))

这将为您提供所需的结果(即两个模式匹配在一起并带有组的所有位置)。

更新:通过额外的澄清,这仍然可以使用单个正则表达式完成。您只需要使上面的两个组都是可选的,即

(?=(A))?(?=(AB))?(?:(?:A)|(?:AB))

然而,我不建议这样做。你可以更容易地分别查找每个模式,然后将结果合并。

string = "AABAABA"
result = [(g.start(), g.group()) for g in re.compile('A').finditer(string)]
result += [(g.start(), g.group()) for g in re.compile('AB').finditer(string)]

不错!这似乎正是我想要的。 - Mikael Lepistö
我在问题中添加了澄清的注释。这个解决方案确实只给出了两个模式都匹配的匹配项。对于上面的评论案例,它们将是(1,['A','AB'])和(4,['A','AB'])。 - Mikael Lepistö
顺便问一下,re.compile('AB').finditer(string) 真的有用吗? re.finditer('AD',string) 应该就可以了,或者如果你非常想要预编译它,那么在列表推导式之外进行编译也可以起到澄清表达式的作用。 - Evpok

3
我理解到这一点,尽管我无法回忆起来是从哪里或谁那里得到的。
def myfindall(regex, seq):
    resultlist = []
    pos = 0
    while True:
        result = regex.search(seq, pos)
        if result is None:
            break
        resultlist.append(seq[result.start():result.end()])
        pos = result.start() + 1
    return resultlist

它返回一个所有匹配项(甚至重叠的)的列表,每个索引只能有一个匹配项的限制。


如果上面的代码似乎只返回'A',而不匹配'AB'。 - Mikael Lepistö
真的,与没有独占部分的匹配不会中断。顺便问一下,https://dev59.com/5m035IYBdhLWcg3wHsKR#5616910 这个链接可行吗? - Evpok
不是真的。我之前尝试过那样做,但它并不像我想要的那样工作。它只为匹配字符串的每个索引执行一次匹配。最终我编写了一个简单的查找表解析器,因为这是一个相当棘手的正则表达式案例。 - Mikael Lepistö
我没有意识到Python有一个单独的“search”函数,而“match”只匹配字符串的开头:http://docs.python.org/2/library/re.html#search-vs-match - n611x007

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