Python Regex Findall non-greedy

Viewed 95

I am relatively new to regex and I seem to be struggling to understand the greedy vs non-greedy search (if that is indeed the issue here). Let's say I have a simple text such as this:

# numbers: 4 A 3 B

My goal would be to run a findall to get something like the following output:

['# number:', '4 A 3 B', ' 4 A', ' 3 B']

So if I use the following regex with findall, I would expect it to work:

matches = re.findall(r"(# numbers:)(((?:\s\d)(?:\s\D))*)", "# numbers: 4 A 3 B")

However, the actual output is this:

[('# numbers:', ' 4 A 3 B', ' 3 B')]

Can someone explain why the group ((\s\d)(\d\D)) is only matching ' 3 B' and not also ' 4 A'? I assume it has something to do with the greedy vs. non-greedy search of * is that true? And if so, could you explain how to solve this issue?

Thanks in advance!

1 Answers

I would use re.findall here, twice. First, extract the digit/non digit text series, then use re.findall a second time to find the tuples:

inp = "# numbers: 4 A 3 B"
text = re.findall(r'^# numbers:\s+(.*)$', inp)[0]
matches = re.findall(r'(\d+)\s+(\D+)', text)
print(matches)  # [('4', 'A '), ('3', 'B')]
Related