Вы путаете группы без захвата (?:...)
и прогнозные утверждения (?=...)
.
Первые действительно участвуют в матче (и, таким образом, являются частью 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 @