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()
.
Ответы
Ответ 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).