我正在尝试从一个可以匹配三种模式之一的字符串中提取数据集。我有一个已编译的正则表达列表。我想通过他们(按顺序)完成第一场比赛。
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!!!'
这应该有效(尚未测试),但它非常难看。有没有更好的方法来煮沸一个循环,当它成功时会中断,或者当它没有时会爆炸?
re
可能存在一些我不了解的特定内容,允许您测试多个模式。
答案 0 :(得分:6)
您可以使用for
循环的else子句:
for reg in regexes:
m = reg.match(name)
if m: break
else:
print 'ARGL NOTHING MATCHES THIS!!!'
答案 1 :(得分:2)
如果您只是想知道是否有任何正则表达式匹配,那么您可以使用内置any
函数:
if any(reg.match(name) for reg in regexes):
....
然而,这不会告诉你哪个正则表达式匹配。
或者,您可以将多个模式合并为一个带有|
的正则表达式:
regex = re.compile(r"(regex1)|(regex2)|...")
同样,这不会告诉您哪个正则表达式匹配,但您将拥有一个匹配对象,您可以使用该对象获取更多信息。例如,您可以找出哪个正则表达式来自非None的组:
>>> match = re.match("(a)|(b)|(c)|(d)", "c")
>>> match.groups()
(None, None, 'c', None)
然而,这可能会变得复杂,但是如果任何子正则表达式中也包含组,因为编号将会改变。
这可能比单独匹配每个正则表达式更快,因为正则表达式引擎有更多优化正则表达式的空间。
答案 2 :(得分:1)
由于在这种情况下你有一个有限集,你可以使用short ciruit evaluation:
m = compiled_regex_1.match(name) or
compiled_regex_2.match(name) or
compiled_regex_3.match(name) or
print("ARGHHHH!")
答案 3 :(得分:1)
在Python 2.6或更高版本中:
import itertools as it
m = next(it.ifilter(None, (r.match(name) for r in regexes)), None)
可以将ifilter
调用转换为genexp,但只是有点笨拙,即在genexp中使用通常的名称绑定技巧(也就是“幻影嵌套for
子句惯用法”) :
m = next((m for r in regexes for m in (r.match(name),) if m), None)
但itertools
通常更适用。
需要2.6
的位是next
内置的,如果迭代器耗尽,则允许您指定默认值。如果你必须在2.5或更早的时候模拟它,
def next(itr, deft):
try: return itr.next()
except StopIteration: return deft
答案 4 :(得分:0)
我使用像Dave Kirby建议的东西,但是将命名组添加到regexp中,以便我知道哪一个匹配。
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
答案 5 :(得分:0)
Eric在更好地了解OP瞄准的目标方面处于更好的状态,但我会使用if else。我也认为在or
表达式中使用print函数是有点可疑的。为Nathon +1修正OP以使用其他正确的声明。
然后我的另类:
# 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!!!')