2014-01-27 3 views
1

Во многих моих проектах python мне приходится проходить через файл, сопоставлять строки с регулярными выражениями, а затем выполнять некоторые вычисления на основе элементов из строки, выделенной регулярным выражением.Назначить и проверить регулярное выражение в Python?

В коде псевдо-C, это довольно-легко:

while (read(line)) 
{ 
    if (m=matchregex(regex1,line)) 
    { 
     /* munch on the components extracted in regex1 by accessing m */ 
    } 
    else if (m=matchregex(regex2,line)) 
    { 
     /* munch on the components extracted in regex2 by accessing m */ 
    } 
    else if ... 
    ... 
    else 
    { 
     error("Unrecognized line format"); 
    } 
} 

Однако, поскольку питон не допускает задание в условном из, если это не может быть сделано элегантно. Сначала можно было бы разобрать все регулярные выражения, а затем сделать if на различных объектах совпадения, но это не является ни элегантным, ни эффективным.

То, что я считаю себя делать вместо этого, включая код, как это на базовом уровне каждого проекта:

im=None 
img=None 
def imps(p,s): 
    global im 
    global img 
    im=re.search(p,s) 
    if im: 
     img=im.groups() 
     return True 
    else: 
     img=None 
     return False 

Тогда я могу работать так:

for line in open(file,'r').read().splitlines(): 
    if imps(regex1,line): 
     # munch on contents of img 
    elsif imps(regex2,line): 
     # munch on contents of img 
    else: 
     error('Unrecognised line: {}'.format(line)) 

Это работает, достаточно компактен, , и легко печатается. Но это вряд ли красиво; он использует глобальные переменные и не является потокобезопасным (что до сих пор не было проблемой для меня).

Но я уверен, что другие раньше столкнулись с этой проблемой и придумали не менее компактный, но более простой python-y и, как правило, превосходное решение. Что это?

ответ

2

В зависимости от потребностей кода.

Общего выбор я использую что-то вроде этого:

# note, order is important here. The first one to match will exit the processing 
parse_regexps = [ 
    (r"^foo", handle_foo), 
    (r"^bar", handle_bar), 
] 

for regexp, handler in parse_regexps: 
    m = regexp.match(line) 
    if m: 
     handler(line) # possibly other data too like m.groups 
     break 
else: 
    error("Unrecognized format....") 

Это имеет преимущество, переместив код обработки в четкие и очевидные функции, что делает тестирование и изменить легко.

1

Вы можете просто использовать continue:

for line in file: 
    m = re.match(re1, line) 
    if m: 
     do stuff 
     continue 

    m = re.match(re2, line) 
    if m: 
     do stuff 
     continue 

    raise BadLine 

Другой, менее очевидный, вариант иметь такую ​​функцию:

def match_any(subject, *regexes): 
    for n, regex in enumerate(regexes): 
     m = re.match(regex, subject) 
     if m: 
      return n, m 
    return -1, None 

, а затем:

for line in file: 
    n, m = match_any(line, re1, re2) 
    if n == 0: 
     .... 
    elif n == 1: 
     .... 
    else: 
     raise BadLine 
+0

Мне нравится продолжить решение и будет использовать его чаще, если бы не обычный случай, что мне часто нужно что-то делать с каждым действующим лином e после сопоставления. – CarlEdman

Смежные вопросы