Подтвердить что ты не робот

Python - поиск и поиск regex

Мне нужно найти все совпадения в строке для данного регулярного выражения. Я использовал findall() для этого, пока не наткнулся на случай, когда он не делал то, что я ожидал. Например:

regex = re.compile('(\d+,?)+')
s = 'There are 9,000,000 bicycles in Beijing.'

print re.search(regex, s).group(0)
> 9,000,000

print re.findall(regex, s)
> ['000']

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

findall() соответствует всем вхождениям шаблона, а не только первому как search().

  • Почему поведение отличается?

  • Как я могу достичь результата search() с помощью findall() (или что-то еще)?

4b9b3361

Ответ 1

Хорошо, я вижу, что происходит... из документов:

Если одна или несколько групп присутствуют в шаблоне, верните список групп;     это будет список кортежей, если шаблон имеет более одной группы.

Как оказалось, у вас есть группа, "(\ d +,?)"... поэтому, что она возвращает, это последнее вхождение этой группы или 000.

Одним из решений является окружение всего регулярного выражения группой, например

regex = re.compile('((\d+,?)+)')

тогда он вернет [('9,000,000', '000')], который является кортежем, содержащим обе сопоставленные группы. конечно, вы заботитесь только о первом.

Лично я бы использовал следующее regex

regex = re.compile('((\d+,)*\d+)')

чтобы избежать совпадения таких вещей, как "это плохое число 9,123",

Изменить.

Здесь можно избежать окружения выражения скобками или обработать кортежи

s = "..."
regex = re.compile('(\d+,?)+')
it = re.finditer(regex, s)

for match in it:
  print match.group(0)

finditer возвращает итератор, который вы можете использовать для доступа ко всем найденным совпадениям. эти объекты соответствия те же, что и re.search, поэтому group (0) возвращает ожидаемый результат.

Ответ 2

@aleph_null answer правильно объясняет причину вашей проблемы, но я думаю, что у меня есть лучшее решение. Используйте это регулярное выражение:

regex = re.compile(r'\d+(?:,\d+)*')

Некоторые причины, почему это лучше:

  • (?:...) - не захватывающая группа, поэтому вы получите только один результат для каждого соответствия.

  • \d+(?:,\d+)* - лучшее регулярное выражение, более эффективное и менее вероятное возвращение ложных срабатываний.

  • Вы всегда должны использовать исходные строки Python для регулярных выражений, если это возможно; вы вряд ли будете удивлены последовательностями escape-выражения регулярных выражений (например, \b для границы слова), которые интерпретируются как последовательности escape-последовательностей строк (например, \b для backspace).