Perl, как регулярное выражение в Python
В Perl я бы сделал что-то подобное для того, чтобы использовать разные поля в регулярном выражении, разделяя разные поля на() и получая их с помощью $
foreach $line (@lines)
{
$line =~ m/(.*?):([^-]*)-(.*)/;
$field_1 = $1
$field_2 = $2
$field_3 = $3
}
Как я могу сделать что-то подобное в Python?
Ответы
Ответ 1
"Канонический" перевод вашего фрагмента на Python...:
import re
myre = re.compile(r'(.*?):([^-]*)-(.*)')
for line in lines:
mo = myre.search(line)
field_1, field_2, field_3 = mo.groups()
Импортирование re
является обязательным (импорт обычно выполняется в верхней части модуля, но это необязательно). Предварительная компиляция RE необязательна (если вместо этого вы используете функцию re.search
, она будет компилировать ваш шаблон "на лету" ), но рекомендуется (поэтому вы не полагаетесь на кеш модуля скомпилированных объектов RE для своей производительности, а также в порядке иметь объект RE и вызывать его методы, которые чаще встречаются в Python).
Вы можете использовать либо метод match
(который всегда пытается совместить с запуском, независимо от того, начинается или нет ваш шаблон с помощью '^'
), либо метод search
(который пытается найти что-то в любом месте); с вашим шаблоном они должны быть эквивалентными (но я не уверен на 100%).
Метод .groups()
возвращает все сопоставляемые группы, поэтому вы можете назначить их все в одном gulp (используя список в Python, как и использование массива в Perl, вероятно, будет более нормальным, но поскольку вы решили использовать скаляры в Perl вы тоже можете сделать в Python).
Это приведет к ошибке с исключением, если какая-либо строка не соответствует RE, и это нормально, если вы знаете, что все они соответствуют (я не уверен, что такое поведение вашего Perl, но я думаю, что он "повторно использовал" предыдущий сопоставляя значения строк, что является своеобразным... если только вы не узнаете, что все строки соответствуют;-). Если вы хотите просто пропустить несогласованные строки, измените последнее утверждение на следующие два:
if mo:
field_1, field_2, field_3 = mo.groups()
Ответ 2
В Perl вам будет гораздо лучше использовать массив, чем суффикс кучи скаляров с числами. Например.
foreach my $line ( @lines ) {
my @matches = ( $line =~ m/(.*?):([^-]*)-(.*)/ );
...
}
В Python модуль re
возвращает объект соответствия, содержащий информацию группы захвата. Поэтому вы можете написать:
match = re.search( '(.*?):([^-]*)-(.*)', line )
Затем ваши совпадения будут доступны в match.group(1)
, match.group(2)
и т.д.
Ответ 3
Python поддерживает регулярные выражения с помощью модуля re
. Метод re.search()
возвращает MatchObject
, который имеет методы типа group()
, которые вы можете использовать для извлечения информации о группе захвата.
Например:
m = re.search(r'(.*?):([^-]*)-(.*)', line)
field_1 = m.group(1)
field_2 = m.group(2)
field_3 = m.group(3)
Ответ 4
И не забывайте, что в Python, TIMTOWTDI;)
import re
p = re.compile(r'(\d+)\.(\d+)')
num_parts = p.findall('11.22 333.444') # List of tuples.
print num_parts # [('11', '22'), ('333', '444')]
Ответ 5
Как альтернативный пример, python обеспечивает очень приятную поддержку названных групп захвата (на самом деле python впервые оказал поддержку названным группам захвата).
Чтобы использовать именованную группу захвата, просто добавьте ?P<the_name_of_the_group>
в открывающую скобку группы захвата.
Это позволяет легко получить все ваши совпадения в словаре:
>>> import re
>>> x = re.search("name: (?P<name>\w+) age: (?P<age>\d+)", "name: Bob age: 20")
>>> x.groupdict()
{'age': '20', 'name': 'Bob'}
Здесь пример OP, измененный для использования названных групп захвата
import re
find_fields_regex = re.compile(r'(?P<field1>.*?):(?P<field2>[^-]*)-(?P<field3>.*)')
for line in lines:
search_result = find_fields_regex.search(line)
all_the_fields = search_result.groupdict()
Теперь all_the_fields
- словарь с ключами, соответствующими именам группы захвата ( "поле1", "поле2" и "поле3" ) и значениям, соответствующим содержимому соответствующих групп захвата.
Почему вам следует выбирать имена групп захвата
- С именованными группами захвата не имеет значения, измените ли вы шаблон регулярного выражения, чтобы добавить больше групп захвата или удалить существующие группы захвата, все по-прежнему помещается в словарь под правильными клавишами. Но без названных групп захвата вам нужно дважды проверять свои назначения переменных каждый раз, когда число групп изменяется.
- Именованные группы захвата делают ваши группы захвата самодокументированными.
- Вы все равно можете использовать номера для ссылки на группы, если хотите:
>>> import re
>>> x = re.search("name: (?P<name>\w+) age: (?P<age>\d+)", "name: Bob age: 20")
>>> x.groupdict()
{'age': '20', 'name': 'Bob'}
>>> x.group(1)
'Bob'
>>> x.group(2)
'20'
Некоторые хорошие ресурсы регулярных выражений: