Python, сравнивающий строку с несколькими регулярными выражениями

Я довольно испытан с Perl и Ruby, но в новинку для Python, таким образом, я надеюсь, что кто-то может показать мне Pythonic способ выполнить следующую задачу. Я хочу сравнить несколько строк с несколькими регулярными выражениями и получить группу соответствия. В Ruby это было бы что-то вроде этого:

# Revised to show variance in regex and related action.
data, foo, bar = [], nil, nil
input_lines.each do |line|
  if line =~ /Foo(\d+)/
    foo = $1.to_i
  elsif line =~ /Bar=(.*)$/
    bar = $1
  elsif bar
    data.push(line.to_f)
  end
end

Мои попытки в Python оказываются довольно ужасными, потому что группа соответствия возвращается из вызова для соответствования/искания на регулярном выражении, и Python не имеет никакого присвоения в условных выражениях или операторах переключения. Что является Pythonic способ сделать (или думать!) об этой проблеме?

6
задан maerics 5 May 2010 в 09:41
поделиться

4 ответа

Решение Пола Макгуайра использования промежуточного класса REMatcher , который выполняет сопоставление, сохраняет группу совпадений и возвращает логическое значение для успеха / неудачи получилось выдать наиболее разборчивый код для этой цели.

0
ответ дан 17 December 2019 в 22:11
поделиться

В Python есть несколько способов "привязать имя на лету", например, мой старый рецепт "назначить и проверить"; в данном случае я бы, вероятно, выбрал другой такой способ (предполагается, что Python 2. 6, нужны небольшие изменения, если вы работаете со старой версией Python), что-то вроде:

import re
pats_marks = (r'^A:(.*)$', 'FOO'), (r'^B:(.*)$', 'BAR')
for line in lines:
    mo, m = next(((mo, m) for p, m in pats_mark for mo in [re.match(p, line)] if mo),
                 (None, None))
    if mo: print '%s: %s' % (m, mo.group(1))
    else: print 'NO MATCH: %s' % line

Многие мелкие детали, конечно, могут быть скорректированы (например, я просто выбрал (.*), а не (.*?) в качестве группы соответствия - они эквивалентны, учитывая непосредственно следующий $, поэтому я выбрал более короткую форму;-) -- Вы могли бы предварительно скомпилировать REs, вычислить вещи иначе, чем кортеж pats_mark (например, с диктой, индексированной шаблонами RE), и т.д.

Но основные идеи, я думаю, заключаются в том, чтобы сделать структуру управляемой данными, и привязывать объект match к имени на лету с помощью подвыражения for mo in [re. match(p, line)], "циклом" по списку из одного элемента (genexps связывает имена только циклом, а не присваиванием - некоторые считают использование этой части спецификаций genexps "хитрым", но я считаю это вполне приемлемой идиомой Python, особенно потому, что она рассматривалась еще во времена разработки listcomps, в некотором смысле "предков" genexps).

1
ответ дан 17 December 2019 в 22:11
поделиться

ваше регулярное выражение просто принимает все, что находится после третьего символа и далее.

for line in open("file"):
    if line.startswith("A:"):
        print "FOO #{"+line[2:]+"}"
    elif line.startswith("B:"):
        print "BAR #{"+line[2:]+"}"
    else:
        print "No match"
-1
ответ дан 17 December 2019 в 22:11
поделиться

Что-то вроде этого, но красивее:

regexs = [re.compile('...'), ...]

for regex in regexes:
  m = regex.match(s)
  if m:
    print m.groups()
    break
else:
  print 'No match'
1
ответ дан 17 December 2019 в 22:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: