How to find out the number of times group was matched in Python regular expressions?

Viewed 81

Metacharacter +: one or more occurrences. What is the general method to get the number of this occurrences?

For example:

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'>

I want to get: [('01', 2), ('02', 3)] due to (10)+ and (20)+ in regex.

3 Answers

One way you could do this is to enclose each repeating capture group inside another group, then you can divide the length of the outer match by the length of the inner match to determine how many times each inner group matched. For example:

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))

Output:

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

You are using re, but as an alternative using regex with the PyPi regex module you could use the same pattern and make use counting the captures() which gives a list of all the captures of a group.

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)

Output

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

Python demo

This is not supported by regular expression engine, you would have to do it yourself. In this case you can capture both the repeated string and the result of the repetition, then count the repetitions yourself.

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)

Note that it won't work on a non-fixed subpatterns. In this case, you would have to run findall (or finditer) on the match group itself and count.

Related