Как узнать, сколько раз группа была сопоставлена в регулярных выражениях Python?

#python #regex

Вопрос:

Метасимвол : одно или несколько вхождений. Каков общий метод получения количества таких случаев?

Например:

 import re

x = re.finditer(r'0(10) (20) ', '0001010202020000')
for i in iter(x):
  print(i) # <re.Match object; span=(2, 13), match='01010202020'>
 

Я хочу получить: [('01', 2), ('02', 3)] из-за (10) и (20) в регулярном выражении.

Комментарии:

1. Вы имеете [('10', 2), ('20', 3)] в виду, когда вы сопоставляете повторения 10 и 20?

2. да, [(’10’, 2), (’20’, 3)] из-за повторений 10 и 20

Ответ №1:

Один из способов сделать это-заключить каждую повторяющуюся группу захвата в другую группу, затем вы можете разделить длину внешнего совпадения на длину внутреннего совпадения, чтобы определить, сколько раз совпадала каждая внутренняя группа. Например:

 import re

m = re.search(r'0((10) )((20) )', '0001010202020000')
num_grps = len(m.groups())
for i in range(1, num_grps 1,2):
    outer = m.end(i) - m.start(i)
    inner = m.end(i 1) - m.start(i 1)
    print((m.group(i 1), outer//inner))
 

Выход:

 ('10', 2)
('20', 3)
 

Ответ №2:

Вы используете re , но в качестве альтернативы, используя regex модуль регулярных выражений PyPI, вы можете использовать тот же шаблон и использовать подсчет captures() , который дает список всех захватов группы.

 import regex

x = regex.search(r'0(10) (20) ', '0001010202020000')
res = []
for i, val in enumerate(x.groups(), 1):
    res.append((val, len(x.captures(i))))

print(res)
 

Выход

 [('10', 2), ('20', 3)]
 

Демо-версия Python

Комментарии:

1. Еще одна удобная функция regex . кстати, вы можете передать 1 в качестве второго параметра enumerate (т. Е. enumerate(x.groups(), 1) ), чтобы он начал отсчет с 1 вместо 0 и сохранил значение 1 вкл i .

2. @Ник Спасибо за совет, каждый день узнаю что-то новое: -)

3. Казалось бы, это справедливо с тех пор, как я узнал об .captures этом от тебя 🙂 Я должен провести еще немного времени с регулярным выражением pypi…

Ответ №3:

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

 matches = re.finditer(r'0((10) )((20) )', '0001010202020000')
for match in matches:
    item = [(pattern, len(instance) // len(pattern))
            for instance, pattern in zip(*[iter(match.groups())]*2)]
    print(item)
 

Обратите внимание, что он не будет работать с нефиксированными подшаблонами. В этом случае вам придется запустить findall (или finditer ) саму группу совпадений и посчитать.