Python - Создание нескольких дополнительных групп в регулярном выражении - PullRequest
3 голосов
/ 07 августа 2020

У меня две строки, часть из которых необязательна. Итак, я попытался создать необязательный шаблон, используя ? после каждой группы, которую я хочу сделать необязательной. Но это дает None в качестве вывода для этих групп.

Text-1:

text1 = '95031B2\tR\tC01 N1 P93 R-- 12:39:18.540 08/05/20 0000002802 R  -                               No_barcode  FLC   F  LR    7.673353 sccm   Pt   25.288202 psig   FL  536.651917 sccm   EDC   0.000000 sccm   PQ    7.668324 sccm   QF  536.289246 sccm   QP   25.287605 psig   LLQ  -0.109524 sccm   HLQ   4.440174 sccm   CLF   1.429953 sccm   MF    0.000000 sccm   LF  100.000015 sccm   MQF   0.000000 sccm   LQF 100.000015 sccm   FPR  25.290846 psig \r\n'

Текст-2:

text2 = '5102060\tR\tC01 N1 P93 R-- 12:38:52.140 08/05/20 0000002801 FO -                               No_barcode \r\n'

Рабочий шаблон для text1 :

pattern1 = ['(?P<time>\d\d:\d\d:\d\d.\d{3})\s',
           '(?P<date>\d\d/\d\d/\d\d)\s',
           '(?P<sno>\d{10})\s',
           '(?P<status>\w{1,2}).*?-',
           '\s*',
           '(?P<bcode>No_barcode|\W{20})',
           '\s{2}',
           '(?P<type>\w{3})',
           '.*?',
           '(?P<pr>Pt.*?\d*[.]?\d*\s[a-z]+)'
           '\s{1,3}',
           '(?P<fl>FL.*?\d*[.]?\d*\s[a-z]+)'
           ]

Пытался сделать необязательную часть в вышеприведенном шаблоне для работы с обеими строками:

>>> pattern2 = ['(?P<time>\d\d:\d\d:\d\d.\d{3})\s', # time pattern
           '(?P<date>\d\d/\d\d/\d\d)\s',           # date pattern
           '(?P<sno>\d{10})\s',                    # 10 digits
           '(?P<status>\w{1,2}).*?-',              # 1 or 2 alphabets follows with anything and then hyphen('-')
           '\s*',                                  # zero or more spaces
           '(?P<bcode>No_barcode|\W{20})',         # No_barcode or any alphanumeric with 20 length
                                       
                     # OPTIONAL PART STARTS (Not working)
           '(\s{1,2}|',                            # 1 or 2 spaces or
           '(?P<type>\w{3})|',                     # 3 alphabets or
           '.*?|',                                 # anything getting ignored or
           '(?P<pr>Pt.*?\d*[.]?\d*\s[a-z]+)|'      # Pt digits optional decimal followed with digits, 1 space, 1 or more a-z alphabets or
           '\s{1,3}|',                             # 1 to 3 spaces or
           '(?P<fl>FL.*?\d*[.]?\d*\s[a-z]+))?'     # FL digits optional decimal followed with digits, 1 space, 1 or more a-z alphabets 
           ]

Выход:

>>> res = re.search(r''.join(pattern1), text) # pattern1
>>> res.groups()
('12:39:18.540', '08/05/20', '0000002802', 'R', 'No_barcode', 'FLC', 'Pt   25.288202 psig', 'FL  536.651917 sccm')
>>> res = re.search(r''.join(pattern2), text) # pattern2, trying to get same output as pattern1
>>> res.groups()
('12:39:18.540', '08/05/20', '0000002802', 'R', 'No_barcode', '  ', None, None, None)

Ожидаемый результат:

Для pattern2 (после добавления необязательной части к pattern1) я должен получить тот же результат, что и результат pattern1.

>>> res = re.search(r''.join(pattern2), text) # pattern2
>>> res.groups()
('12:39:18.540', '08/05/20', '0000002802', 'R', 'No_barcode', 'FLC', 'Pt   25.288202 psig', 'FL  536.651917 sccm')

1 Ответ

1 голос
/ 07 августа 2020

Вы обернули всю часть после обязательной части необязательной группой и вставили | оператор чередования между каждой строкой в ​​шаблоне, что является неправильным способом создания дополнительных групп.

Если части являются необязательными, и последующие подшаблоны не зависят от того, найден ли предыдущий подшаблон или нет, вам нужно либо обернуть каждую часть дополнительной группой: <obligatory_part>(?:...(optional_1)...)?(?:...(optional_2)...)?(?:...(optional_n)...)?.

Или создать вложенные дополнительные группы, если каждая последующий шаблон не может появиться, если предыдущий подшаблон отсутствует: <obligatory_part>(?:...(optional_1)...(?:...(optional_2)...(?:...(optional_n)...)?)?)?.

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

(?P<time>\d\d:\d\d:\d\d.\d{3})\s(?P<date>\d\d/\d\d/\d\d)\s(?P<sno>\d{10})\s(?P<status>\w{1,2}).*?-\s*(?P<bcode>No_barcode|\W{20})(?:\s+(?P<type>\w{3}))?(?:.*?(?P<pr>Pt.*?\d*[.]?\d*\s[a-z]+))?(?:\s{1,3}(?P<fl>FL.*?\d*[.]?\d*\s[a-z]+))?

или это regex :

(?P<time>\d\d:\d\d:\d\d.\d{3})\s(?P<date>\d\d/\d\d/\d\d)\s(?P<sno>\d{10})\s(?P<status>\w{1,2}).*?-\s*(?P<bcode>No_barcode|\W{20})(?:\s+(?P<type>\w{3})(?:.*?(?P<pr>Pt.*?\d*[.]?\d*\s[a-z]+)(?:\s{1,3}(?P<fl>FL.*?\d*[.]?\d*\s[a-z]+))?)?)?

Поскольку вы говорите, что вам нужна Схема 1, вы можете использовать

pattern = [r'(?P<time>\d\d:\d\d:\d\d.\d{3})\s',
           r'(?P<date>\d\d/\d\d/\d\d)\s',
           r'(?P<sno>\d{10})\s',
           r'(?P<status>\w{1,2}).*?-',
           r'\s*',
           r'(?P<bcode>No_barcode|\W{20})',
           r'(?:\s+',                     # (?: starts a non-capturing group...
           r'(?P<type>\w{3}))?',          # ...)? closes the group, 
           r'(?:.*?',
           r'(?P<pr>Pt.*?\d*[.]?\d*\s[a-z]+))?'
           r'(?:\s{1,3}',
           r'(?P<fl>FL.*?\d*[.]?\d*\s[a-z]+))?'
          ]
print(r''.join(pattern))

См. Python demo .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...