Как использовать re () в группах Python и Return Capture в выражении «If»? - PullRequest
0 голосов
/ 03 марта 2019

Хотя я использую 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\\\n\n", $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:\tmp\a.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() или match.groups() ...

Python Code:

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 Ответ

0 голосов
/ 03 марта 2019

Сначала нужно проверить совпадение, а затем использовать группы.Т.е.

  • скомпилируйте регулярные выражения (необязательно для большинства случаев в настоящее время, согласно документации)
  • примените каждое регулярное выражение к строке для создания объекта совпадения
    • 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")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...