从正则表达式列表中查找第一个匹配的正则表达式

时间:2015-11-22 14:45:41

标签: python regex

假设我有一个像这样的正则表达式列表(这是一个简单的例子,真正的代码有更复杂的正则表达式):

regs = [r'apple', 'strawberry', r'pear', r'.*berry', r'fruit: [a-z]*']

我希望完全匹配上面的一个正则表达式(所以^regex$)并返回索引。另外,我想匹配最左边的正则表达式。所以find('strawberry')应该返回1而find('blueberry')应该返回3.我将重复使用同一组正则表达式,因此预计算很好。

这是我编码的内容,但感觉很糟糕。正则表达式应该能够知道哪一个匹配,我觉得这非常低效(请记住上面的例子是简化的,真正的正则表达式更复杂,数量更多):

import re

regs_compiled = [re.compile(reg) for reg in regs]
regs_combined = re.compile('^' +
                           '|'.join('(?:{})'.format(reg) for reg in regs) +
                           '$')

def find(s):
    if re.match(regs_combined, s):
        for i, reg in enumerate(regs_compiled):
            if re.match(reg, s):
                return i

    return -1

有没有办法找出哪些子表达式用于匹配正则表达式而没有显式循环?

1 个答案:

答案 0 :(得分:4)

确定正则表达式的哪个子表达式与字符串匹配的唯一方法是对每个子句使用捕获组,然后检查哪个组不是None。但这要求子表达式不会单独使用捕获组。

E.g。

>>> regs_combined = re.compile('^' +
                           '|'.join('({})'.format(reg) for reg in regs) +
                           '$')
>>> m = re.match(regs_combined, 'strawberry')
>>> m.groups()
(None, 'strawberry', None, None, None)
>>> m.lastindex - 1
1

除此之外,标准正则表达式实现不提供进一步的信息。当然,您可以构建自己的引擎来公开该信息,但除了非常特殊的用例之外,很难在其他情况下使其实际工作 - 这可能是现有解决方案无法提供的原因。