我正在尝试将 @ 字符之前的电子邮件地址的本地部分与:
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)
为什么正则表达式不拒绝带有一对点 '..'
的字符串?
最佳答案
您混淆了非捕获组 (?:...)
和先行断言 (?=...)
。
前者确实参与了匹配(因此是包含整体匹配的 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 @
关于python - 前瞻和非捕获正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7040829/