4

我正在尝试将@字符之前的电子邮件地址的本地部分与:

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)

为什么正则表达式不拒绝带有一对点的字符串'..'

4

1 回答 1

8

您混淆了非捕获组(?:...)和前瞻断言(?=...)

前者确实参与了比赛(因此是比赛的一部分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 @
于 2011-08-12T14:08:45.217 回答