Возвращает строку с первым соответствием Regex

Я хочу получить первое совпадение регулярного выражения.

В этом случае я получил список:

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

['33', '44']

Я мог бы извлечь первый элемент списка:

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

'33'

Но это работает только если есть хотя бы одно совпадение, иначе я получу ошибку:

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

IndexError: индекс индекса вне диапазона

В этом случае я мог бы определить функцию:

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

Есть ли способ получить этот результат без определения новой функции?

Ответы

Ответ 1

Вы можете вставлять значение '' по умолчанию в ваше регулярное выражение, добавляя |$:

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

Также работает с re.search, указанным другими:

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

Ответ 2

Если вам нужно только первое совпадение, используйте re.search вместо 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'

Затем вы можете использовать m в качестве условия проверки как:

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


First number found = 33

Ответ 3

Вы не должны использовать .findall() вообще - .search() - это то, что вы хотите. Он находит самое левое совпадение, которое вы хотите (или возвращает None, если совпадение не существует).

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

Если вы хотите поместить это в функцию, зависит от вас. Необязательно возвращать пустую строку, если совпадение не найдено, поэтому ничего подобного не встроено. Невозможно запутаться в том, что сам .search() находит совпадение (он возвращает None, если он не был 't или объект SRE_Match, если это так).

Ответ 4

Я бы пошел с:

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

re.search все равно ищет первое совпадение в строке, поэтому я думаю, что это делает ваше намерение немного более понятным, чем использование findall.

Ответ 5

Вы можете сделать:

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

Обратите внимание, что ваш вопрос не совсем связан с регулярным выражением. Скорее, как вы можете безопасно найти элемент из массива, если он не имеет.

Ответ 6

Возможно, это будет немного лучше, если большее количество входных данных не будет содержать ваш желаемый фрагмент, потому что, кроме того, он имеет большую стоимость.

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