Use re.findall or re.finditer instead.
re.findall(pattern, string) returns a list of matching strings.
re.finditer(pattern, string) returns an iterator over MatchObject objects.
Example:
re.findall( r'all (.*?) are', 'all cats are smarter than dogs, all dogs are dumber than cats')
# Output: ['cats', 'dogs']
[x.group() for x in re.finditer( r'all (.*?) are', 'all cats are smarter than dogs, all dogs are dumber than cats')]
# Output: ['all cats are', 'all dogs are']
Answer from Amber on Stack OverflowUse re.findall or re.finditer instead.
re.findall(pattern, string) returns a list of matching strings.
re.finditer(pattern, string) returns an iterator over MatchObject objects.
Example:
re.findall( r'all (.*?) are', 'all cats are smarter than dogs, all dogs are dumber than cats')
# Output: ['cats', 'dogs']
[x.group() for x in re.finditer( r'all (.*?) are', 'all cats are smarter than dogs, all dogs are dumber than cats')]
# Output: ['all cats are', 'all dogs are']
Another method (a bit in keeping with OP's initial spirit albeit 13 years later) is to compile the pattern and call search() on the compiled pattern and move along the pattern. This is a bit verbose but if you don't want a lookahead etc. or you want to search over a string more explicitly, then you can use the following function.
import re
def find_all_matches(pattern, string, group=0):
pat = re.compile(pattern)
pos = 0
out = []
while m := pat.search(string, pos):
pos = m.start() + 1
out.append(m[group])
return out
pat = r'all (.*?) are'
s = 'all cats are smarter than dogs, all dogs are dumber than cats'
find_all_matches(pat, s) # ['all cats are', 'all dogs are']
find_all_matches(pat, s, group=1) # ['cats', 'dogs']
This works for overlapping matches too:
find_all_matches(r'(\w\w)', "hello") # ['he', 'el', 'll', 'lo']
Ok, I see what's going on... from the docs:
If one or more groups are present in the pattern, return a list of groups; this will be a list of tuples if the pattern has more than one group.
As it turns out, you do have a group, "(\d+,?)"... so, what it's returning is the last occurrence of this group, or 000.
One solution is to surround the entire regex by a group, like this
regex = re.compile('((\d+,?)+)')
then, it will return [('9,000,000', '000')], which is a tuple containing both matched groups. of course, you only care about the first one.
Personally, i would use the following regex
regex = re.compile('((\d+,)*\d+)')
to avoid matching stuff like " this is a bad number 9,123,"
Edit.
Here's a way to avoid having to surround the expression by parenthesis or deal with tuples
s = "..."
regex = re.compile('(\d+,?)+')
it = re.finditer(regex, s)
for match in it:
print match.group(0)
finditer returns an iterator that you can use to access all the matches found. these match objects are the same that re.search returns, so group(0) returns the result you expect.
@aleph_null's answer correctly explains what's causing your problem, but I think I have a better solution. Use this regex:
regex = re.compile(r'\d+(?:,\d+)*')
Some reasons why it's better:
(?:...)is a non-capturing group, so you only get the one result for each match.\d+(?:,\d+)*is a better regex, more efficient and less likely to return false positives.You should always use Python's raw strings for regexes if possible; you're less likely to be surprised by regex escape sequences (like
\bfor word boundary) being interpreted as string-literal escape sequences (like\bfor backspace).