Я бы ожидал следующее регулярное выражение
re.match(r"^(.*?)(b?)(.*?)$", s).groups()
для сопоставления с тремя непустыми группами .. потому что средняя часть шаблона жадная
Нет, вы не должны этого ожидать. На самом деле, такое поведение очень ожидаемо по следующей причине:
Вы специально указали регулярное выражение в первой группе, чтобы оно было lazy , что означает, что оно будет принимать наименьшее количество символов (которое в данном случае равно нулю) ) потому что ничто иное не заставляет его искать больше. Таким образом, хотя регулярное выражение во второй группе является жадным (то есть b?
), оно по-прежнему не может соответствовать b
, поскольку позиция по-прежнему равна 0.
Вы можете подтвердить это, заменив вторую группу на (.?)
, которая в этом случае будет соответствовать a
, , а не b
, как вы могли бы ожидать . Вот демо для ^(.*?)(.?)(.*?)$
.
Теперь, если бы ваши правила запрещали отсутствие b
, вы могли бы легко изменить свое регулярное выражение на ^(.*?)(b)(.*?)$
, но, так как вы хотите, чтобы первая группа продолжала соответствовать , если b
существует , но в то же время разрешено отсутствовать b
(т. е. вторая группа может фактически быть пустой), тогда это решение не решает проблему.
Единственное решение, которое приходит мне в голову на данный момент и удовлетворяющее этим двум условиям, - это использовать Lookahead , чтобы определить, существует ли b
или нет. Вот пример:
^((?:.*?(?=b))|.*?)(b?)(.*?)$
Попробуйте онлайн .
Это продолжит сопоставление любых символов (используя .
), пока не найдет b
, а затем остановится, в противном случае (т. Е. Если нет b
), оно будет прекращать сопоставление всякий раз, когда количество символов наименьшее можно найти (это оригинальное поведение). Другими словами, это гарантирует, что вторая группа не пуста , пока существует b
.
Пожалуйста, дайте мне знать, если это не соответствует ни одному из ваших условий.