Захват групп с оператором или в Python - PullRequest
4 голосов
/ 03 мая 2019

Я обнаружил странное поведение в Python 3.7.0 при захвате групп с помощью оператора или, когда одна ветвь изначально совпадает, но регулярное выражение должно в конечном итоге вернуться назад и использовать другую ветвь. В этом сценарии группы захвата придерживаются первой ветви, хотя регулярное выражение использует вторую ветвь.

Пример кода:

regexString = "^(a)|(ab)$"

captureString = "ab"

match = re.match(regexString, captureString)

print(match.groups())

Выход:

('a', None)

Вторая группа - это группа, которая используется, но первая группа захвачена, а вторая - нет.

Интересно, что я нашел обходной путь, добавив не захватывающие скобки вокруг обеих групп следующим образом:

regexString = "^(?:(a)|(ab))$"

Новый вывод:

(None, 'ab')

Для меня это поведение выглядит как ошибка. Если это не так, может кто-нибудь указать мне на документацию, объясняющую, почему это происходит? Спасибо!

1 Ответ

6 голосов
/ 03 мая 2019

Это распространенная ошибка регулярного выражения.Вот ваш оригинальный шаблон:

^(a)|(ab)$

Это фактически говорит о совпадении ^a, то есть a в начале ввода или ab$, то есть ab вконец ввода.Если вместо этого вы хотите сопоставить a или ab как весь ввод, тогда, как вы выяснили, вам нужно:

^(?:(a)|(ab))$

Чтобы еще больше убедить себя в этом, вы можете проверить, что следующий шаблонсоответствует тем же вещам, что и ваш исходный шаблон:

(ab)$|^(a)

То есть каждый чередующийся член является отдельным, и положение даже не имеет значения, по крайней мере, в отношении того, какие входные данные будут совпадать или не совпадать.Кстати, вы могли бы просто использовать следующий шаблон:

^ab?$

Это будет соответствовать a или ab, а также вам даже не понадобится группа захвата, так как все совпадение будет соответствоватьк тому, что вы хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...