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

2 番目の問題 (ダブル ドットが一致するのはなぜですか?) は、少しトリッキーです。これは、正規表現のエラーが原因です。ほら、あなたが書いたとき(ポイントを作るために短縮されています)

[+-/]

+「との間の文字に一致し/、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 に答える