Как сжато каскадировать несколько операторов regex в Python
Моя дилемма: я передаю свою функцию строку, в которой мне нужно выполнить многочисленные манипуляции с регулярными выражениями. Логика - это совпадение в первом регулярном выражении, сделайте одно. Если нет совпадения, проверьте совпадение со вторым и сделайте что-нибудь еще, если не проверьте третий, и так далее. Я мог бы сделать что-то вроде этого:
if re.match('regex1', string):
match = re.match('regex1', string)
# Manipulate match.group(n) and return
elif re.match('regex2', string):
match = re.match('regex2', string)
# Do second manipulation
[etc.]
Однако это кажется излишне подробным, и обычно, когда это дело, это означает, что лучший способ, который я либо игнорирую, либо еще не знаю.
Есть ли у кого-нибудь предложение для лучшего способа сделать это (лучше с точки зрения внешнего вида кода, точки использования памяти или обоих)?
Ответы
Ответ 1
Аналогичный вопрос с сентября по сентябрь: Как вы переводите эту идиому регулярного выражения из Perl в Python?
Использование глобальных переменных в модуле, возможно, не лучший способ сделать это, но преобразование его в класс:
import re
class Re(object):
def __init__(self):
self.last_match = None
def match(self,pattern,text):
self.last_match = re.match(pattern,text)
return self.last_match
def search(self,pattern,text):
self.last_match = re.search(pattern,text)
return self.last_match
gre = Re()
if gre.match(r'foo',text):
# do something with gre.last_match
elif gre.match(r'bar',text):
# do something with gre.last_match
else:
# do something else
Ответ 2
Вообще говоря, в таких ситуациях вы хотите сделать код "управляемым данными". То есть, поместите важную информацию в контейнер и пропустите ее.
В вашем случае важная информация - это пара (строка, функция).
import re
def fun1():
print('fun1')
def fun2():
print('fun2')
def fun3():
print('fun3')
regex_handlers = [
(r'regex1', fun1),
(r'regex2', fun2),
(r'regex3', fun3)
]
def example(string):
for regex, fun in regex_handlers:
if re.match(regex, string):
fun() # call the function
break
example('regex2')
Ответ 3
У меня была такая же проблема, как у вас. Вот мое решение:
import re
regexp = {
'key1': re.compile(r'regexp1'),
'key2': re.compile(r'regexp2'),
'key3': re.compile(r'regexp3'),
# ...
}
def test_all_regexp(string):
for key, pattern in regexp.items():
m = pattern.match(string)
if m:
# do what you want
break
Это немного измененное решение из ответа Извлечение информации из больших структурированных текстовых файлов
Ответ 4
Хм... вы могли бы что-то использовать с конструкцией with
... um
class rewrapper()
def __init__(self, pattern, target):
something
def __enter__(self):
something
def __exit__(self):
something
with rewrapper("regex1", string) as match:
etc
with rewrapper("regex2", string) as match:
and so forth
Ответ 5
Являются ли манипуляции для каждого регулярного выражения похожими? Если да, попробуйте следующее:
for regex in ('regex1', 'regex2', 'regex3', 'regex4'):
match = re.match(regex, string)
if match:
# Manipulate match.group(n)
return result
Ответ 6
Здесь ваши регулярные выражения и совпадения не повторяются дважды:
match = re.match('regex1', string)
if match:
# do stuff
return
match = re.match('regex2', string)
if match:
# do stuff
return
Ответ 7
class RegexStore(object):
_searches = None
def __init__(self, pat_list):
# build RegEx searches
self._searches = [(name,re.compile(pat, re.VERBOSE)) for
name,pat in pat_list]
def match( self, text ):
match_all = ((x,y.match(text)) for x,y in self._searches)
try:
return ifilter(op.itemgetter(1), match_all).next()
except StopIteration, e:
# instead of 'name', in first arg, return bad 'text' line
return (text,None)
Вы можете использовать этот класс следующим образом:
rs = RegexStore( (('pat1', r'.*STRING1.*'),
('pat2', r'.*STRING2.*')) )
name,match = rs.match( "MY SAMPLE STRING1" )
if name == 'pat1':
print 'found pat1'
elif name == 'pat2':
print 'found pat2'