Я должен попробовать строку против нескольких (эксклюзивный - значение строки, которая соответствует одному из них, не может соответствовать ни одному из другого), regexes, и выполните другую часть кода, в зависимости от которого это соответствует. Что я имею, в настоящее время:
m = firstre.match(str)
if m:
# Do something
m = secondre.match(str)
if m:
# Do something else
m = thirdre.match(str)
if m:
# Do something different from both
Кроме уродства, этот код соответствует против всего regexes даже после того, как это соответствовало одному из них (скажите, что firstre), который неэффективен. Я пытался использовать:
elif m = secondre.match(str)
но изученный, что присвоению не позволяют войти если операторы.
Существует ли изящный способ достигнуть того, что я хочу?
def doit( s ):
# with some side-effect on a
a = []
def f1( s, m ):
a.append( 1 )
print 'f1', a, s, m
def f2( s, m ):
a.append( 2 )
print 'f2', a, s, m
def f3( s, m ):
a.append( 3 )
print 'f3', a, s, m
re1 = re.compile( 'one' )
re2 = re.compile( 'two' )
re3 = re.compile( 'three' )
func_re_list = (
( f1, re1 ),
( f2, re2 ),
( f3, re3 ),
)
for myfunc, myre in func_re_list:
m = myre.match( s )
if m:
myfunc( s, m )
break
doit( 'one' )
doit( 'two' )
doit( 'three' )
Несколько идей, ни одна из них не обязательно хороша, но она может хорошо подойти к вашему коду:
Как насчет того, чтобы поместить код в отдельную функцию, т.е. MatchRegex()
, которая возвращает тот регекс, которому он соответствовал. Таким образом, внутри функции можно использовать возврат после совпадения первого (или второго) регрекса, то есть потерять эффективность.
Конечно, вы всегда можете использовать только вложенные , если
высказывания:
m = firstre.match(str)
if m:
# Do something
else:
m = secondre.match(str)
...
Я действительно не вижу причин не использовать вложенные , если
. Они очень просты в понимании и эффективны настолько, насколько вы хотите. Я бы пошёл за ними только ради их простоты.
Может быть, скоро вернется?
def doit(s):
m = re1.match(s)
if m:
# Do something
return
m = re2.match(s)
if m:
# Do something else
return
...
Ответ Муравья Аасмы тоже хорош. Если вы предпочитаете меньше шаблонов, вы можете написать это самостоятельно, используя подробный синтаксис регулярных выражений .
re = re.compile(r'''(?x) # set the verbose flag
(?P<foo> fo+ )
| (?P<bar> ba+r )
| #...other alternatives...
''')
def doit(s):
m = re.match(s)
if m.group('foo'):
# Do something
elif m.group('bar'):
# Do something else
...
Я делал это много раз. Это быстро и работает с re.finditer
.
Возможно, это немного выходит за рамки проектирования решения, но вы можете объединить их как один регеxp с именованными группами и посмотреть, какая группа подходит. Это может быть инкапсулировано как вспомогательный класс:
import re
class MultiRe(object):
def __init__(self, **regexps):
self.keys = regexps.keys()
self.union_re = re.compile("|".join("(?P<%s>%s)" % kv for kv in regexps.items()))
def match(self, string, *args):
result = self.union_re.match(string, *args)
if result:
for key in self.keys:
if result.group(key) is not None:
return key
Поиск будет выглядеть следующим образом:
multi_re = MultiRe(foo='fo+', bar='ba+r', baz='ba+z')
match = multi_re.match('baaz')
if match == 'foo':
# one thing
elif match == 'bar':
# some other thing
elif match == 'baz':
# or this
else:
# no match
Это хорошее приложение для недокументированного, но довольно полезного класса re.Scanner.
Вы можете использовать
def do_first(str, res, actions):
for re,action in zip(res, actions):
m = re.match(str)
if m:
action(str)
return
Так, например, вы определили
def do_something_1(str):
print "#1: %s" % str
def do_something_2(str):
print "#2: %s" % str
def do_something_3(str):
print "#3: %s" % str
firstre = re.compile("foo")
secondre = re.compile("bar")
thirdre = re.compile("baz")
Затем вызовите его с помощью
do_first("baz",
[firstre, secondre, thirdre],
[do_something_1, do_something_2, do_something_3])
Сделайте это с помощью elif, если вам просто нужно соответствие True / False вне регулярного выражения:
if regex1.match(str):
# do stuff
elif regex2.match(str):
# and so on