'Return string with first match for a regex, handling case where there is no match

I want to get the first match of a regex.

In this case, I have a list:

text = 'aa33bbb44'
re.findall('\d+',text)

['33', '44']

I could extract the first element of the list:

text = 'aa33bbb44'
re.findall('\d+',text)[0]

'33'

But that only works if there is at least one match, otherwise I'll get an error:

text = 'aazzzbbb'
re.findall('\d+',text)[0]

IndexError: list index out of range

In which case I could define a function:

def return_first_match(text):
    try:
        result = re.findall('\d+',text)[0]
    except Exception, IndexError:
        result = ''
    return result

Is there a way of obtaining that result without defining a new function?



Solution 1:[1]

You could embed the '' default in your regex by adding |$:

>>> re.findall('\d+|$', 'aa33bbb44')[0]
'33'
>>> re.findall('\d+|$', 'aazzzbbb')[0]
''
>>> re.findall('\d+|$', '')[0]
''

Also works with re.search pointed out by others:

>>> re.search('\d+|$', 'aa33bbb44').group()
'33'
>>> re.search('\d+|$', 'aazzzbbb').group()
''
>>> re.search('\d+|$', '').group()
''

Solution 2:[2]

If you only need the first match, then use re.search instead of re.findall:

>>> m = re.search('\d+', 'aa33bbb44')
>>> m.group()
'33'
>>> m = re.search('\d+', 'aazzzbbb')
>>> m.group()
Traceback (most recent call last):
  File "<pyshell#281>", line 1, in <module>
    m.group()
AttributeError: 'NoneType' object has no attribute 'group'

Then you can use m as a checking condition as:

>>> m = re.search('\d+', 'aa33bbb44')
>>> if m:
        print('First number found = {}'.format(m.group()))
    else:
        print('Not Found')


First number found = 33

Solution 3:[3]

I'd go with:

r = re.search("\d+", ch)
result = return r.group(0) if r else ""

re.search only looks for the first match in the string anyway, so I think it makes your intent slightly more clear than using findall.

Solution 4:[4]

You shouldn't be using .findall() at all - .search() is what you want. It finds the leftmost match, which is what you want (or returns None if no match exists).

m = re.search(pattern, text)
result = m.group(0) if m else ""

Whether you want to put that in a function is up to you. It's unusual to want to return an empty string if no match is found, which is why nothing like that is built in. It's impossible to get confused about whether .search() on its own finds a match (it returns None if it didn't, or an SRE_Match object if it did).

Solution 5:[5]

You can do:

x = re.findall('\d+', text)
result = x[0] if len(x) > 0 else ''

Note that your question isn't exactly related to regex. Rather, how do you safely find an element from an array, if it has none.

Solution 6:[6]

Maybe this would perform a bit better in case greater amount of input data does not contain your wanted piece because except has greater cost.

def return_first_match(text):
    result = re.findall('\d+',text)
    result = result[0] if result else ""
    return result

Solution 7:[7]

just assign the results to a variable then iterate the variable

 text = 'aa33bbb44'
 result=re.findall('\d+',text)
 for item in result:
     print(item)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 erb
Solution 3 Daniel Holmes
Solution 4 Tim Peters
Solution 5 ketan vijayvargiya
Solution 6 Marko Mackic
Solution 7 Golden Lion