Жадный режим квантификаторов в Python на примерах
В этом уроке вы узнаете о жадном режиме квантификаторов в Python и о том, как изменить его с жадного (greedy) на нежадный (non-greedy).
По умолчанию все квантификаторы работают в жадном режиме. Это означает, что квантификаторы будут стараться максимально соответствовать своим предыдущим элементам.
Начнем с примера, чтобы понять, как работает regex greedy.
Неожиданный результат с жадным квантификатором
Предположим, у вас есть следующий фрагмент HTML, представляющий элемент button:
s = '<button type="submit" class="btn">Send</button>'
И вы хотите сопоставить тексты в кавычках(«»), например submit и btn.
Для этого вы можете придумать следующий шаблон, включающий кавычку(«), набор символов точки(.) и квантификатор(+):
".+"
Смысл паттерна следующий:
- » — начинается с цитаты
- . — соответствует любому символу, кроме новой строки
- + — соответствует предыдущему символу один или несколько раз
- » — заканчивается цитатой
В следующем примере используется функция finditer() для сопоставления строки s с шаблоном:
import re s = '<button type="submit" class="btn">Send</button>' pattern = '".+"' matches = re.finditer(pattern, s) for match in matches: print(match.group())
Программа выдает следующий результат:
"submit" class="btn"
Результат не тот, что вы ожидали.
По умолчанию квантификатор(+) работает в жадном режиме, в котором он пытается максимально соответствовать предыдущему элементу(«.).
Как работает regex greedy в Python
Сначала механизм регулярных выражений начинает сопоставление с первого символа строки s.
Далее, поскольку первый символ — <, который не соответствует кавычке(«), механизм регулярных выражений продолжает сопоставлять следующие символы, пока не достигнет первой кавычки(«):
Затем механизм регулярных выражений проверяет шаблон и сопоставляет строку со следующим правилом .+.
Поскольку правило .+ соответствует символу один или несколько раз, механизм регулярных выражений сопоставляет все символы, пока не достигнет конца строки:
После этого механизм регулярных выражений проверяет последнее правило шаблона — кавычку(«). Однако он уже достигает конца строки. Больше нет подходящего персонажа. Это слишком жадно, чтобы зайти слишком далеко.
Наконец, механизм регулярных выражений возвращается от конца строки, чтобы найти кавычку («). Этот шаг называется backtracking.
В результате совпадением является следующая подстрока, которая не соответствует нашим ожиданиям:
"submit" class="btn"
Чтобы устранить эту проблему, вам нужно указать квантификатору(+) использовать нежадный (или ленивый) режим вместо жадного режима.
Для этого вы добавляете вопросительный знак (?) после квантификатора следующим образом:
".+?"
Следующая программа возвращает ожидаемый результат:
import re s = '<button type="submit" class="btn">Send</button>' pattern = '".+?"' matches = re.finditer(pattern, s) for match in matches: print(match.group())
Выход:
"submit" "btn"