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

PythonRegex

Python Problem Overview


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?

Python Solutions


Solution 1 - Python

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

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

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

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

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

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

just assign the results to a variable then iterate the variable

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLuis Ramon Ramirez RodriguezView Question on Stackoverflow
Solution 1 - PythonStefan PochmannView Answer on Stackoverflow
Solution 2 - PythonIron FistView Answer on Stackoverflow
Solution 3 - PythonBillView Answer on Stackoverflow
Solution 4 - PythonTim PetersView Answer on Stackoverflow
Solution 5 - Pythonketan vijayvargiyaView Answer on Stackoverflow
Solution 6 - PythonMarko MackicView Answer on Stackoverflow
Solution 7 - PythonGolden LionView Answer on Stackoverflow