упреждающие и не захватывающие регулярные выражения - PullRequest
3 голосов
/ 12 августа 2011

Я пытаюсь сопоставить локальную часть адреса электронной почты перед символом @ с:

LOCAL_RE_NOTQUOTED = """
((
\w         # alphanumeric and _
| [!#$%&'*+-/=?^_`{|}~]          # special chars, but no dot at beginning
)
(
\w         # alphanumeric and _
| [!#$%&'*+-/=?^_`{|}~]          # special characters
| ([.](?![.])) # negative lookahead to avoid pairs of dots. 
)*)
(?<!\.)(?:@)           # no end with dot before @
"""

Тестирование с:

re.match(LOCAL_RE_NOTQUOTED, "a.a..a@", re.VERBOSE).group()

дает:

'a.a..a@'

Почему @ печатается на выходе, хотя я использую группу без захвата (?:@)?

Тестирование с:

 re.match(LOCAL_RE_NOTQUOTED, "a.a..a@", re.VERBOSE).groups()

дает:

('a.a..a', 'a', 'a', None)

Почему регулярное выражение не отклоняет строку с парой точек '..'?

1 Ответ

6 голосов
/ 12 августа 2011

Вы путаете группы без захвата (?:...) и прогнозные утверждения (?=...).

Первые действительно участвуют в матче (и, таким образом, являются частью match.group(), которая содержит общее совпадение),они просто не генерируют обратную ссылку ($1 и т. д. для последующего использования).

Вторая проблема (почему двойная точка соответствует?) немного сложнее.Это из-за ошибки в вашем регулярном выражении.Видите ли, когда вы написали (сокращено, чтобы подчеркнуть смысл)

[+-/]

, вы написали «Совпадение символа между + и /, а в ASCII точка находится прямо между ними (ASCII 43-47: +,-./). Следовательно, первый класс символов совпадает с точкой, и утверждение о заглядывании никогда не достигается. Вам нужно поместить тире в конец класса символов, чтобы рассматривать его как буквальный тире:

((
\w         # alphanumeric and _
| [!#$%&'*+/=?^_`{|}~-]          # special chars, but no dot at beginning
)
(
\w         # alphanumeric and _
| [!#$%&'*+/=?^_`{|}~-]          # special characters
| ([.](?![.])) # negative lookahead to avoid pairs of dots. 
)*)
(?<!\.)(?=@)           # no end with dot before @

И, конечно, если вы хотите использовать эту логику, вы можете немного ее упростить:

^(?!\.)                   # no dot at the beginning
(?:
[\w!#$%&'*+/=?^_`{|}~-]   # alnums or special characters except dot
| (\.(?![.@]))            # or dot unless it's before a dot or @ 
)*
(?=@)                     # end before @
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...