#python #regex
#python #регулярное выражение
Вопрос:
Хотя я использую Perl много лет, у меня всегда были проблемы с чем-то большим, чем простое использование регулярных выражений в языке. Сейчас ситуация только хуже, поскольку я пытаюсь выучить Python… и использование re () для меня еще более непонятно.
Я пытаюсь проверить соответствие, есть ли подстрока в строке, используя re(), а также использую группы захвата для извлечения некоторой информации из процесса сопоставления. Однако я не могу заставить вещи работать в нескольких контекстах; при использовании вызова re () и присвоении возвращаемых значений всем в операторе «if» .. и как справиться с ситуацией, когда элементы .groups не определены в объектах сопоставления (когда сопоставление не выполнено).
Итак, ниже приведены примеры того, что я пытаюсь сделать, закодированные на Perl и Python, с их соответствующими выводами.
Я был бы признателен за любые указания о том, как я мог бы лучше подойти к проблеме, используя Python.
Perl-код:
use strict;
use warnings;
my ($idx, $dvalue);
while (my $rec = <DATA>) {
chomp($rec);
if ( ($idx, $dvalue) = ($rec =~ /^XA([0-9] )=(.*?)!/) ) {
printf(" Matched:n");
printf(" rec: >%s<n", $rec);
printf(" index = >%s< value = >%s<n", $idx, $dvalue);
} elsif ( ($idx, $dvalue) = ($rec =~ /^PZ([0-9] )=(.*?[^#])!/) ) {
printf(" Matched:n");
printf(" rec: >%s<n", $rec);
printf(" index = >%s< value = >%s<n", $idx, $dvalue);
} else {
printf("n Unknown Record format, \%s\nn", $rec);
}
}
close(DATA);
exit(0)
__DATA__
DUD=ABC!QUEUE=D23!
XA32=7!P^=32!
PZ112=123^!PQ=ABC!
Вывод на Perl:
Unknown Record format, DUD=ABC!QUEUE=D23!
Matched:
rec: >XA32=7!P^=32!<
index = >32< value = >7<
Matched:
rec: >PZ112=123^!PQ=ABC!<
index = >112< value = >123^<
Код Python:
import re
string = 'XA32=7!P^=32!'
with open('data.dat', 'r') as fh:
for rec in fh:
orec = ' rec: >' rec.rstrip('n') '<'
print(orec)
# always using 'string' at least lets this program run
(index, dvalue) = re.search(r'^XA([0-9] )=(.*?[^#])!', string).groups()
# The following works when there is a match... but fails with an error when
# a match is NOT found, viz:-
# ...
# (index, dvalue) = re.search(r'^XA([0-9] )=(.*?[^#])!', rec).groups()
#
# Traceback (most recent call last):
# File "T:tmpa.py", line 13, in <module>
# (index, dvalue) = re.search(r'^XA([0-9] )=(.*?[^#])!', rec).groups()
# AttributeError: 'NoneType' object has no attribute 'groups'
#
buf = ' index = >' index '<' ' value = >' dvalue '<'
print(buf)
exit(0)
содержимое data.dat:
DUD=ABC!QUEUE=D23!
XA32=7!P^=32!
PZ112=123^!PQ=ABC!
Вывод на Python:
rec: >DUD=ABC!QUEUE=D23!<
index = >32< value = >7<
rec: >XA32=7!P^=32!<
index = >32< value = >7<
rec: >PZ112=123^!PQ=ABC!<
index = >32< value = >7<
Еще одна разработка: еще немного кода, который поможет мне лучше понять это… но я не уверен, когда / как использовать match.group()
or match.groups()
…
Код Python:
import re
rec = 'XA22=11^!S^=64!ABC=0,0!PX=0!SP=12B!'
print("rec = >{}<".format(rec))
# ----
index = 0 ; dvalue = 0 ; x = 0
match = re.match(r'XA([0-9] )=(.*?[^#])!(.*?)!', rec)
if match:
(index, dvalue, x) = match.groups()
print("3 (): index = >{}< value = >{}< x = >{}<".format(index, dvalue, x))
# ----
index = 0 ; dvalue = 0 ; x = 0
match = re.match(r'XA([0-9] )=(.*?[^#])!', rec)
if match:
(index, dvalue) = match.groups()
print("2 (): index = >{}< value = >{}< x = >{}<".format(index, dvalue, x))
# ----
index = 0 ; dvalue = 0 ; x = 0
match = re.match(r'XA([0-9] )=', rec)
if match:
#(index) = match.groups() # Why doesn't this work like above examples!?
(index, ) = match.groups() # ...and yet this works!?
# Does match.groups ALWAYS returns a tuple!?
#(index) = match.group(1) # This also works; 0 = entire matched string?
print("1 (): index = >{}< value = >{}< x = >{}<".format(index, dvalue, x))
# ----
index = 0 ; dvalue = 0 ; x = 0
match = re.search(r'S^=([0-9] )!', rec)
if match:
(index, ) = match.groups() # Returns tuple(?!)
print("1 (): index = >{}< value = >{}< x = >{}<".format(index, dvalue, x))
Опять же, я был бы признателен за любые мысли о том, какой способ является «предпочтительным» .. или если есть другой способ работы с группами.
Комментарии:
1. Если вы хотите узнать о регулярных выражениях, я бы рекомендовал прочитать Джеффри Фридла — Освоение регулярных выражений .
2. @StefanBecker Я хорошо знаю книгу Friedl.. но мне трудно разобраться (очень похоже на «Программирование на Python» О’Рейли.. Фух! ). Я чаще всего ссылаюсь на Кулинарную книгу по регулярным выражениям Гойвартса и Левитана. .
3. Лучше всего, если вы скажете, чего вы хотите достичь, а не предоставляете это на другом языке. (Если, конечно, проблема не в понимании кода Perl, и в этом случае это должен быть ваш вопрос.) Поскольку этот вопрос имеет не больше отношения к Perl, чем к английскому, я удаляю тег.
Ответ №1:
Сначала вам нужно проверить соответствие, а затем использовать группы. Т.е.
- скомпилируйте регулярные выражения (необязательно для большинства случаев в настоящее время, согласно документации)
- применяйте каждое регулярное выражение к строке, чтобы сгенерировать объект соответствия
match()
совпадает только в начале строки, т. Е. с неявным^
привязкойsearch()
совпадает с любым местом в строке
- проверьте, является ли объект соответствия допустимым
- извлеките группы
- переход к следующей итерации цикла
# works with Python 2 and Python 3
import re
with open('dummy.txt', 'r') as fh:
for rec in fh:
orec = ' rec: >' rec.rstrip('n') '<'
print(orec)
match = re.match(r'XA([0-9] )=(.*?[^#])!', rec)
if match:
(index, dvalue) = match.groups()
print(" index = >{}< value = >{}<".format(index, dvalue))
continue
match = re.match(r'PZ([0-9] )=(.*?[^#])!', rec)
if match:
(index, dvalue) = match.groups()
print(" index = >{}< value = >{}<".format(index, dvalue))
continue
print(" Unknown Record format")
Вывод:
$ python dummy.py
rec: >DUD=ABC!QUEUE=D23!<
Unknown Record format
rec: >XA32=7!P^=32!<
index = >32< value = >7<
rec: >PZ112=123^!PQ=ABC!<
index = >112< value = >123^<
Но мне интересно, почему вы не упростите свой код на Perl и Python, просто используя вместо этого одно регулярное выражение? Например.:
match = re.match(r'(?:XA|PZ)([0-9] )=(.*?[^#])!', rec)
if match:
(index, dvalue) = match.groups()
print(" index = >{}< value = >{}<".format(index, dvalue))
else:
print(" Unknown Record format")
Комментарии:
1. Есть несколько отличных идей, спасибо. В «реальной» программе ‘XA’, ‘PZ’ и т.д. насчитывают около 10 элементов… и выполняемые действия различаются в зависимости от каждого «тега», отсюда и эффективное действие «переключения»… но хорошая мысль.