#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)]
Комментарии:
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
) саму группу совпадений и посчитать.