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?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 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()
''

Method 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

Method 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.

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

Method 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.

Method 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

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


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x