Нежадные регулярные выражения Python


151

Как сделать питона регулярное выражение , как , "(.*)"например , что при "a (b) c (d) e"питон соответствует "b"вместо "b) c (d"?

Я знаю, что я могу использовать "[^)]"вместо ".", но я ищу более общее решение, которое держит мое регулярное выражение немного чище. Есть ли способ сказать Python "Эй, сопоставьте это как можно скорее"?

Ответы:


209

Ты ищешь всесильного *?

Из документов, Жадный против Нежадных

не-жадные классификаторы *?, +?, ??или {m,n}?[...] матч , как маленький текст , насколько это возможно.


Согласно Интернет-архиву, все, на что ссылалась эта ссылка, было копией документации по модулю Python «re», так что ссылка Трея работает так же хорошо.
spiffytech

2
какое общее английское название для этого *??
Тревор Бойд Смит

Подстановочные знаки @Trevor Бойд Смит
Серж

3
Это называется "не жадный" квалификатор
brunetton

65
>>> x = "a (b) c (d) e"
>>> re.search(r"\(.*\)", x).group()
'(b) c (d)'
>>> re.search(r"\(.*?\)", x).group()
'(b)'

Согласно документам :

Спецификаторы ' *', ' +' и ' ?' являются жадными; они соответствуют как можно большему количеству текста. Иногда такое поведение нежелательно; если RE <.*>сопоставлено с ' <H1>title</H1>', оно будет соответствовать всей строке, а не только ' <H1>'. Добавление ' ?' после квалификатора заставляет его выполнять матч нежадным или минимальным образом; будет сопоставлено как можно меньше символов. Использование .*?в предыдущем выражении будет соответствовать только ' <H1>'.


14

Не будет \\(.*?\\)работать? Это не жадный синтаксис.


5

Как сказали другие, используя? Модификатор * quantifier решит вашу непосредственную проблему, но будьте осторожны, вы начинаете отклоняться в области, где регулярные выражения перестают работать, и вместо этого вам нужен анализатор. Например, строка "(foo (bar)) baz" вызовет у вас проблемы.


5

Использование нечестного матча - хорошее начало, но я бы также посоветовал вам пересмотреть любое использование .*- как насчет этого?

groups = re.search(r"\([^)]*\)", x)

3

Вы хотите, чтобы это соответствовало "(b)"? Делай, как предложили Цитракс и Паоло. Вы хотите, чтобы это соответствовало "b"? Делать

>>> x = "a (b) c (d) e"
>>> re.search(r"\((.*?)\)", x).group(1)
'b'

0

Для начала я не предлагаю использовать "*" в регулярных выражениях. Да, я знаю, это наиболее используемый многосимвольный разделитель, но, тем не менее, это плохая идея. Это потому, что, хотя он соответствует любому количеству повторений для этого символа, «any» включает в себя 0, что обычно является причиной того, что вы хотите вызвать синтаксическую ошибку, а не принять. Вместо этого я предлагаю использовать +знак, который соответствует любому повторению длины> 1. Более того, из того, что я вижу, вы имеете дело с выражениями в скобках фиксированной длины. В результате вы, вероятно, можете использовать {x, y}синтаксис, чтобы конкретно указать желаемую длину.

Однако, если вам действительно нужно не жадное повторение, я советую обратиться ко всемогущим ?. Это, после размещения после в конце любого спецификатора повторения регулярного выражения, заставит эту часть регулярного выражения найти наименьшее возможное количество текста.

При этом я был бы очень осторожен с тем, ?как оно, подобно звуковой отвертке в «Докторе Кто», имеет тенденцию делать, как бы это выразиться, «слегка» нежелательные вещи, если не будет тщательно откалиброван. Например, чтобы использовать ваш пример ввода, он идентифицирует ((1)(обратите внимание на отсутствие второго rparen) как совпадение.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.