Regex 从一批正则表达式中获取第一个成功匹配

Regex 从一批正则表达式中获取第一个成功匹配,regex,python,Regex,Python,我试图从一个字符串中提取一组数据,该字符串可以匹配三种模式中的一种。我有一个已编译正则表达式的列表。我想(按顺序)浏览一遍,然后进行第一场比赛 regexes = [ compiled_regex_1, compiled_regex_2, compiled_regex_3, ] m = None for reg in regexes: m = reg.match(name) if m: break if not m: print 'ARGL N

我试图从一个字符串中提取一组数据,该字符串可以匹配三种模式中的一种。我有一个已编译正则表达式的列表。我想(按顺序)浏览一遍,然后进行第一场比赛

regexes = [
    compiled_regex_1,
    compiled_regex_2,
    compiled_regex_3,
]

m = None
for reg in regexes:
    m = reg.match(name)
    if m: break

if not m:
    print 'ARGL NOTHING MATCHES THIS!!!'
这应该是可行的(还没有测试),但它是相当fugly。有没有更好的方法使循环在成功时破裂,或者在失败时爆炸

可能有一些特定于
re
的东西我不知道,它也允许您测试多个模式。

您可以使用
for
循环的子句:

for reg in regexes:
    m = reg.match(name)
    if m: break
else:
    print 'ARGL NOTHING MATCHES THIS!!!'

由于本例中有一个有限集,因此可以使用:


如果您只想知道任何正则表达式是否匹配,则可以使用内置的
any
函数:

if any(reg.match(name) for reg in regexes):
     ....
但是,这不会告诉您哪个正则表达式匹配

或者,您可以使用
|
将多个模式组合成一个正则表达式:

regex = re.compile(r"(regex1)|(regex2)|...")
同样,这不会告诉您哪个正则表达式匹配,但您将有一个match对象,可以用于进一步的信息。例如,您可以找出哪些正则表达式从非无的组中成功:

>>> match = re.match("(a)|(b)|(c)|(d)", "c")
>>> match.groups()
(None, None, 'c', None)
然而,如果任何子正则表达式中也有组,这可能会变得复杂,因为编号将被更改


这可能比单独匹配每个正则表达式要快,因为正则表达式引擎有更大的范围来优化正则表达式。

我使用了Dave Kirby建议的方法,但将命名组添加到正则表达式中,以便知道哪一个匹配

regexps = {
  'first': r'...',
  'second': r'...',
}

compiled = re.compile('|'.join('(?P<%s>%s)' % item for item in regexps.iteritems()))
match = compiled.match(my_string)
print match.lastgroup
regexps={
“第一”:r“…”,
“第二个”:r“…”,
}
compiled=re.compile(“|”).join(“(?P%s)”%item for regexps.iteritems()中的项)
match=compiled.match(我的字符串)
打印match.lastgroup

埃里克在拍摄OP目标的更大画面方面做得更好,不过我会用if-else。我还认为在
表达式中使用print函数没有什么问题+1为纠正OP的Nathon使用适当的else语句

那么我的选择是:

# alternative to any builtin that returns useful result,
# the first considered True value
def first(seq):
    for item in seq:
        if item: return item

regexes = [
    compiled_regex_1,
    compiled_regex_2,
    compiled_regex_3,
]

m = first(reg.match(name) for reg in regexes)
print(m if m else 'ARGL NOTHING MATCHES THIS!!!')

在Python 2.6或更高版本中:

import itertools as it

m = next(it.ifilter(None, (r.match(name) for r in regexes)), None)
ifilter
调用可以在genexp中进行,但只是有点笨拙,即使用genexp中名称绑定的常用技巧(也称为“幻影嵌套
for
子句惯用法”):

但在适用的情况下,
itertools
通常更可取

需要
2.6
的位是内置的
next
,当迭代器耗尽时,它允许您指定默认值。如果必须在2.5或更早版本中进行模拟

def next(itr, deft):
  try: return itr.next()
  except StopIteration: return deft

+1表示正确,但我得到的印象是,for-else构造被认为是令人困惑的,尽管在许多情况下它正是您想要的,但它似乎不受欢迎(但我希望被驳斥)。我不知道那个。虽然我的眼睛总是把
else
try
联系在一起;除了
语句之外,
try
。我发现了关于
for..的
else
至少三次了。。。我总是忘记它。它只是不好的命名,但它确实工作得很好。谢谢,嗯。在我的真实代码中,在打印我的“ARGL…”消息后,我向更高的
for
循环抛出
continue
。如果python想要清晰的代码,他们就不能用
for..else
。请注意,正则表达式的尝试顺序将是未定义的,这可能会产生意外的结果。对,因为我使用了dict。如果改为使用元组列表,或者对该列表中的regexps.items进行排序,那么它就是定义良好的。
m = next((m for r in regexes for m in (r.match(name),) if m), None)
def next(itr, deft):
  try: return itr.next()
  except StopIteration: return deft