メールアドレスの正規表現

更新日 2019/5/3
カウンター

戻る
Perlメモへ - メールアドレスの正規表現
Perl正規表現雑技

更新履歴

2019/05/03 「制御文字を除去する」「参考文献」RFC5321日本語訳のリンク修正
2009/08/13 $atextのバグ修正
2009/05/06 「正規表現を簡略化する」追記
2009/04/29 「旧形式を削除する」追記
2009/04/13 「IPアドレスを除去する」追記

目次


RFCに準拠したメールアドレスの正規表現

メールアドレスについては RFC 5322 に addr-spec として書かれています. 下記は RFC 5322 に従って導き出した正規表現です. 14,277バイトあります. perl 5.10で動作し,コメントのネストにも対応しています.

(?:(?:(?:(?:(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x0
9]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?(\((?:(?:(?:[\x20\x09]*(?:\x0D\x
0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?(?:(
?:[\x21-\x27\x2A-\x5B\x5D-\x7E]|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F])|
(?:\\(?:[\x21-\x7E]|[\x20\x09])|(?:\\(?:\x00|[\x01-\x08\x0B\x0C\x0
E-\x1F\x7F]|\x0A|\x0D)))|(?-1)))*(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\
x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?\)))+(?:(?:
[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)
[\x20\x09]+)*))?|(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x
20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*)))?(?:[A-Za-z0-9!#$%&'*+\-/=?
^_`{|}~]+(?:\.[A-Za-z0-9!#$%&'*+\-/=?^_`{|}~]+)*)(?:(?:(?:(?:[\x20
\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20
\x09]+)*))?(\((?:(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x
20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?(?:(?:[\x21-\x27\x2A-\x5B\x
5D-\x7E]|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F])|(?:\\(?:[\x21-\x7E]|[\x
20\x09])|(?:\\(?:\x00|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|\x0A|\x0D))
)|(?-1)))*(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]
+(?:(?:\x0D\x0A)[\x20\x09]+)*))?\)))+(?:(?:[\x20\x09]*(?:\x0D\x0A)
)?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?|(?:(?:
[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)
[\x20\x09]+)*)))?)|(?:(?:(?:(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x
09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?(\((?:(?:(?:[\x2
0\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x2
0\x09]+)*))?(?:(?:[\x21-\x27\x2A-\x5B\x5D-\x7E]|[\x01-\x08\x0B\x0C
\x0E-\x1F\x7F])|(?:\\(?:[\x21-\x7E]|[\x20\x09])|(?:\\(?:\x00|[\x01
-\x08\x0B\x0C\x0E-\x1F\x7F]|\x0A|\x0D)))|(?-1)))*(?:(?:[\x20\x09]*
(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+
)*))?\)))+(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]
+(?:(?:\x0D\x0A)[\x20\x09]+)*))?|(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\
x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*)))?"(?:(?:(?:
[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)
[\x20\x09]+)*))?(?:(?:[\x21\x23-\x5B\x5D-\x7E]|[\x01-\x08\x0B\x0C\
x0E-\x1F\x7F])|(?:\\(?:[\x21-\x7E]|[\x20\x09])|(?:\\(?:\x00|[\x01-
\x08\x0B\x0C\x0E-\x1F\x7F]|\x0A|\x0D)))))*(?:(?:[\x20\x09]*(?:\x0D
\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?"(
?:(?:(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(
?:\x0D\x0A)[\x20\x09]+)*))?(\((?:(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\
x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?(?:(?:[\x21
-\x27\x2A-\x5B\x5D-\x7E]|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F])|(?:\\(?
:[\x21-\x7E]|[\x20\x09])|(?:\\(?:\x00|[\x01-\x08\x0B\x0C\x0E-\x1F\
x7F]|\x0A|\x0D)))|(?-1)))*(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09
]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?\)))+(?:(?:[\x20\x
09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x
09]+)*))?|(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]
+(?:(?:\x0D\x0A)[\x20\x09]+)*)))?)|(?:(?:(?:(?:(?:(?:(?:[\x20\x09]
*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]
+)*))?(\((?:(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x0
9]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?(?:(?:[\x21-\x27\x2A-\x5B\x5D-\x
7E]|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F])|(?:\\(?:[\x21-\x7E]|[\x20\x0
9])|(?:\\(?:\x00|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|\x0A|\x0D)))|(?-
1)))*(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(
?:\x0D\x0A)[\x20\x09]+)*))?\)))+(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x
20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?|(?:(?:[\x20
\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20
\x09]+)*)))?[A-Za-z0-9!#$%&'*+\-/=?^_`{|}~]+(?:(?:(?:(?:[\x20\x09]
*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]
+)*))?(\((?:(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x0
9]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?(?:(?:[\x21-\x27\x2A-\x5B\x5D-\x
7E]|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F])|(?:\\(?:[\x21-\x7E]|[\x20\x0
9])|(?:\\(?:\x00|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|\x0A|\x0D)))|(?-
1)))*(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(
?:\x0D\x0A)[\x20\x09]+)*))?\)))+(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x
20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?|(?:(?:[\x20
\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20
\x09]+)*)))?)|(?:(?:(?:(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|
(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?(\((?:(?:(?:[\x20\x09
]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09
]+)*))?(?:(?:[\x21-\x27\x2A-\x5B\x5D-\x7E]|[\x01-\x08\x0B\x0C\x0E-
\x1F\x7F])|(?:\\(?:[\x21-\x7E]|[\x20\x09])|(?:\\(?:\x00|[\x01-\x08
\x0B\x0C\x0E-\x1F\x7F]|\x0A|\x0D)))|(?-1)))*(?:(?:[\x20\x09]*(?:\x
0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?
\)))+(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(
?:\x0D\x0A)[\x20\x09]+)*))?|(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x
09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*)))?"(?:(?:(?:[\x20
\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20
\x09]+)*))?(?:(?:[\x21\x23-\x5B\x5D-\x7E]|[\x01-\x08\x0B\x0C\x0E-\
x1F\x7F])|(?:\\(?:[\x21-\x7E]|[\x20\x09])|(?:\\(?:\x00|[\x01-\x08\
x0B\x0C\x0E-\x1F\x7F]|\x0A|\x0D)))))*(?:(?:[\x20\x09]*(?:\x0D\x0A)
)?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?"(?:(?:
(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0
D\x0A)[\x20\x09]+)*))?(\((?:(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x
09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?(?:(?:[\x21-\x27
\x2A-\x5B\x5D-\x7E]|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F])|(?:\\(?:[\x2
1-\x7E]|[\x20\x09])|(?:\\(?:\x00|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|
\x0A|\x0D)))|(?-1)))*(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?
:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?\)))+(?:(?:[\x20\x09]*(
?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)
*))?|(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(
?:\x0D\x0A)[\x20\x09]+)*)))?))(?:\.(?:(?:(?:(?:(?:(?:[\x20\x09]*(?
:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*
))?(\((?:(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+
(?:(?:\x0D\x0A)[\x20\x09]+)*))?(?:(?:[\x21-\x27\x2A-\x5B\x5D-\x7E]
|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F])|(?:\\(?:[\x21-\x7E]|[\x20\x09])
|(?:\\(?:\x00|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|\x0A|\x0D)))|(?-1))
)*(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\
x0D\x0A)[\x20\x09]+)*))?\)))+(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\
x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?|(?:(?:[\x20\x0
9]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x0
9]+)*)))?[A-Za-z0-9!#$%&'*+\-/=?^_`{|}~]+(?:(?:(?:(?:[\x20\x09]*(?
:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*
))?(\((?:(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+
(?:(?:\x0D\x0A)[\x20\x09]+)*))?(?:(?:[\x21-\x27\x2A-\x5B\x5D-\x7E]
|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F])|(?:\\(?:[\x21-\x7E]|[\x20\x09])
|(?:\\(?:\x00|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|\x0A|\x0D)))|(?-1))
)*(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\
x0D\x0A)[\x20\x09]+)*))?\)))+(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\
x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?|(?:(?:[\x20\x0
9]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x0
9]+)*)))?)|(?:(?:(?:(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:
[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?(\((?:(?:(?:[\x20\x09]*(
?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)
*))?(?:(?:[\x21-\x27\x2A-\x5B\x5D-\x7E]|[\x01-\x08\x0B\x0C\x0E-\x1
F\x7F])|(?:\\(?:[\x21-\x7E]|[\x20\x09])|(?:\\(?:\x00|[\x01-\x08\x0
B\x0C\x0E-\x1F\x7F]|\x0A|\x0D)))|(?-1)))*(?:(?:[\x20\x09]*(?:\x0D\
x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?\))
)+(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\
x0D\x0A)[\x20\x09]+)*))?|(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]
+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*)))?"(?:(?:(?:[\x20\x0
9]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x0
9]+)*))?(?:(?:[\x21\x23-\x5B\x5D-\x7E]|[\x01-\x08\x0B\x0C\x0E-\x1F
\x7F])|(?:\\(?:[\x21-\x7E]|[\x20\x09])|(?:\\(?:\x00|[\x01-\x08\x0B
\x0C\x0E-\x1F\x7F]|\x0A|\x0D)))))*(?:(?:[\x20\x09]*(?:\x0D\x0A))?[
\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?"(?:(?:(?:
(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x
0A)[\x20\x09]+)*))?(\((?:(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]
+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?(?:(?:[\x21-\x27\x2
A-\x5B\x5D-\x7E]|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F])|(?:\\(?:[\x21-\
x7E]|[\x20\x09])|(?:\\(?:\x00|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|\x0
A|\x0D)))|(?-1)))*(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\
x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?\)))+(?:(?:[\x20\x09]*(?:\
x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))
?|(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\
x0D\x0A)[\x20\x09]+)*)))?)))*))@(?:(?:(?:(?:(?:(?:[\x20\x09]*(?:\x
0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?
(\((?:(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:
(?:\x0D\x0A)[\x20\x09]+)*))?(?:(?:[\x21-\x27\x2A-\x5B\x5D-\x7E]|[\
x01-\x08\x0B\x0C\x0E-\x1F\x7F])|(?:\\(?:[\x21-\x7E]|[\x20\x09])|(?
:\\(?:\x00|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|\x0A|\x0D)))|(?-1)))*(
?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D
\x0A)[\x20\x09]+)*))?\)))+(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09
]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?|(?:(?:[\x20\x09]*
(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+
)*)))?(?:[A-Za-z0-9!#$%&'*+\-/=?^_`{|}~]+(?:\.[A-Za-z0-9!#$%&'*+\-
/=?^_`{|}~]+)*)(?:(?:(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?
:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?(\((?:(?:(?:[\x20\x09]*
(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+
)*))?(?:(?:[\x21-\x27\x2A-\x5B\x5D-\x7E]|[\x01-\x08\x0B\x0C\x0E-\x
1F\x7F])|(?:\\(?:[\x21-\x7E]|[\x20\x09])|(?:\\(?:\x00|[\x01-\x08\x
0B\x0C\x0E-\x1F\x7F]|\x0A|\x0D)))|(?-1)))*(?:(?:[\x20\x09]*(?:\x0D
\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?\)
))+(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:
\x0D\x0A)[\x20\x09]+)*))?|(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09
]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*)))?)|(?:(?:(?:(?:(?:
[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)
[\x20\x09]+)*))?(\((?:(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(
?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?(?:(?:[\x21-\x27\x2A-\
x5B\x5D-\x7E]|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F])|(?:\\(?:[\x21-\x7E
]|[\x20\x09])|(?:\\(?:\x00|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|\x0A|\
x0D)))|(?-1)))*(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20
\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?\)))+(?:(?:[\x20\x09]*(?:\x0D
\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?|(
?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D
\x0A)[\x20\x09]+)*)))?\[(?:(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x0
9]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?(?:[\x21-\x5A\x5E
-\x7E]|(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|(?:\\(?:[\x21-\x7E]|[\x
20\x09])|(?:\\(?:\x00|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|\x0A|\x0D))
))))*(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(
?:\x0D\x0A)[\x20\x09]+)*))?\](?:(?:(?:(?:[\x20\x09]*(?:\x0D\x0A))?
[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?(\((?:(?:
(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x
0A)[\x20\x09]+)*))?(?:(?:[\x21-\x27\x2A-\x5B\x5D-\x7E]|[\x01-\x08\
x0B\x0C\x0E-\x1F\x7F])|(?:\\(?:[\x21-\x7E]|[\x20\x09])|(?:\\(?:\x0
0|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|\x0A|\x0D)))|(?-1)))*(?:(?:[\x2
0\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x2
0\x09]+)*))?\)))+(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x
20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?|(?:(?:[\x20\x09]*(?:\x0D\x
0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*)))?)|(
?:(?:(?:(?:(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09
]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?(\((?:(?:(?:[\x20\x09]*(?:\x0D\x0
A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?(?:(?
:[\x21-\x27\x2A-\x5B\x5D-\x7E]|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F])|(
?:\\(?:[\x21-\x7E]|[\x20\x09])|(?:\\(?:\x00|[\x01-\x08\x0B\x0C\x0E
-\x1F\x7F]|\x0A|\x0D)))|(?-1)))*(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x
20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?\)))+(?:(?:[
\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[
\x20\x09]+)*))?|(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x2
0\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*)))?[A-Za-z0-9!#$%&'*+\-/=?^_`{
|}~]+(?:(?:(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09
]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?(\((?:(?:(?:[\x20\x09]*(?:\x0D\x0
A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?(?:(?
:[\x21-\x27\x2A-\x5B\x5D-\x7E]|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F])|(
?:\\(?:[\x21-\x7E]|[\x20\x09])|(?:\\(?:\x00|[\x01-\x08\x0B\x0C\x0E
-\x1F\x7F]|\x0A|\x0D)))|(?-1)))*(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x
20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?\)))+(?:(?:[
\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[
\x20\x09]+)*))?|(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x2
0\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*)))?)(?:\.(?:(?:(?:(?:(?:[\x20\
x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\
x09]+)*))?(\((?:(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x2
0\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?(?:(?:[\x21-\x27\x2A-\x5B\x5
D-\x7E]|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F])|(?:\\(?:[\x21-\x7E]|[\x2
0\x09])|(?:\\(?:\x00|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|\x0A|\x0D)))
|(?-1)))*(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+
(?:(?:\x0D\x0A)[\x20\x09]+)*))?\)))+(?:(?:[\x20\x09]*(?:\x0D\x0A))
?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?|(?:(?:[
\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[
\x20\x09]+)*)))?[A-Za-z0-9!#$%&'*+\-/=?^_`{|}~]+(?:(?:(?:(?:[\x20\
x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\
x09]+)*))?(\((?:(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x2
0\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?(?:(?:[\x21-\x27\x2A-\x5B\x5
D-\x7E]|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F])|(?:\\(?:[\x21-\x7E]|[\x2
0\x09])|(?:\\(?:\x00|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|\x0A|\x0D)))
|(?-1)))*(?:(?:[\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+
(?:(?:\x0D\x0A)[\x20\x09]+)*))?\)))+(?:(?:[\x20\x09]*(?:\x0D\x0A))
?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[\x20\x09]+)*))?|(?:(?:[
\x20\x09]*(?:\x0D\x0A))?[\x20\x09]+|(?:[\x20\x09]+(?:(?:\x0D\x0A)[
\x20\x09]+)*)))?))*))

上記の正規表現を求めるスクリプトは下記の通りです.

my $CR = qq{\\x0D};
my $LF = qq{\\x0A};
my $CRLF = qq{(?:\\x0D\\x0A)};
my $VCHAR = qq{[\\x21-\\x7E]};
my $WSP = qq{[\\x20\\x09]};

my $obs_NO_WS_CTL = qq{[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]};
my $obs_ctext = $obs_NO_WS_CTL;
my $obs_qtext = $obs_NO_WS_CTL;
my $obs_qp = qq{(?:\\\\(?:\\x00|$obs_NO_WS_CTL|$LF|$CR))};
my $obs_FWS = qq{(?:$WSP+(?:$CRLF$WSP+)*)};

my $FWS = qq{(?:(?:$WSP*$CRLF)?$WSP+|$obs_FWS)};
my $ctext = qq{(?:[\\x21-\\x27\\x2A-\\x5B\\x5D-\\x7E]|$obs_ctext)};
my $quoted_pair = qq{(?:\\\\(?:$VCHAR|$WSP)|$obs_qp)};
my $ccontent = qq{(?:$ctext|$quoted_pair|(?-1))};
my $comment = qq{(\\((?:$FWS?$ccontent)*$FWS?\\))};
my $CFWS = qq{(?:(?:$FWS?$comment)+$FWS?|$FWS)};

my $atext = qq{[A-Za-z0-9!#\$%&'*+\\-/=?^_`{|}~]};
my $atom = qq{(?:$CFWS?$atext+$CFWS?)};
my $dot_atom_text = qq{(?:$atext+(?:\\.$atext+)*)};
my $dot_atom = qq{(?:$CFWS?$dot_atom_text$CFWS?)};

my $qtext = qq{(?:[\\x21\\x23-\\x5B\\x5D-\\x7E]|$obs_qtext)};
my $qcontent = qq{(?:$qtext|$quoted_pair)};
my $quoted_string = qq{(?:$CFWS?"(?:$FWS?$qcontent)*$FWS?"$CFWS?)};

my $obs_dtext = qq{(?:$obs_NO_WS_CTL|$quoted_pair)};
my $dtext = qq{(?:[\\x21-\\x5A\\x5E-\\x7E]|$obs_dtext)};
my $domain_literal = qq{(?:$CFWS?\\[(?:$FWS?$dtext)*$FWS?\\]$CFWS?)};

my $word = qq{(?:$atom|$quoted_string)};
my $obs_local_part = qq{(?:$word(?:\\.$word)*)};
my $obs_domain = qq{(?:$atom(?:\\.$atom)*)};
my $local_part = qq{(?:$dot_atom|$quoted_string|$obs_local_part)};
my $domain = qq{(?:$dot_atom|$domain_literal|$obs_domain)};
my $addr_spec = qq{$local_part\@$domain};
my $mail_regex = $addr_spec;

このメールアドレスの正規表現 $mail_regex を使って,$email が正しいメールアドレスか判定するには次のように書きます.

# $email が正しいメールアドレス(addr_spec)か判定する

if ($email =~ /\A$mail_regex\z/o) {
  print "正しいメールアドレスです\n";
}

モジュール Email::Valid または モジュール Mail::CheckUser を使うと, メールアドレスが実際に有効かどうかもある程度調べることができます. 詳しい使い方はマニュアルを読んでください.

トップへ

コメントと空白文字を除去する

RFCに準拠したメールアドレスの正規表現 はあまり実用的ではありません. というのも,メールアドレスとして期待している範囲以上のものまで, 正しいメールアドレスとして判定してしまうからです. 例えば,下記の文字列はタブ,スペース,改行(CRLF)まで含んでいますが正しいメールアドレスとして判定されてしまいます.

# Foo.Bar@example.com
my $email = "(Foo Bar (FirstName: Foo) (LastName: Bar))\x0D\x0A" .
  "\x09(FirstName) Foo . (LastName) Bar\x0D\x0A" .
  "\x09\x09\@ example\x0D\x0A\x09\x09\x09(TLD) .com";

(Foo Bar (FirstName: Foo) (LastName: Bar))
        (FirstName) Foo . (LastName) Bar
                @ example
                        (TLD) .com

上記の文字列はCFWS(comments and/or FWS)とFWS(Folding white space) として定義される部分を含むように作成した文字列です. これらコメントや空白文字を含むようなメールアドレスは, 正しいメールアドレスとして判定してほしくない場合がほとんどでしょう. そこで,CFWSとFWSを含まないように修正した正規表現が下記のものです. 989バイトと一気に短くなり, 上記の文字列も正しいメールアドレスとは判定されなくなります.

(?:(?:[A-Za-z0-9!#$%&'*+\-/=?^_`{|}~]+(?:\.[A-Za-z0-9!#$%&'*+\-/=?
^_`{|}~]+)*)|(?:"(?:(?:[\x21\x23-\x5B\x5D-\x7E]|[\x01-\x08\x0B\x0C
\x0E-\x1F\x7F])|(?:\\(?:[\x21-\x7E]|[\x20\x09])|(?:\\(?:\x00|[\x01
-\x08\x0B\x0C\x0E-\x1F\x7F]|\x0A|\x0D))))*")|(?:(?:(?:[A-Za-z0-9!#
$%&'*+\-/=?^_`{|}~]+)|(?:"(?:(?:[\x21\x23-\x5B\x5D-\x7E]|[\x01-\x0
8\x0B\x0C\x0E-\x1F\x7F])|(?:\\(?:[\x21-\x7E]|[\x20\x09])|(?:\\(?:\
x00|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|\x0A|\x0D))))*"))(?:\.(?:(?:[
A-Za-z0-9!#$%&'*+\-/=?^_`{|}~]+)|(?:"(?:(?:[\x21\x23-\x5B\x5D-\x7E
]|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F])|(?:\\(?:[\x21-\x7E]|[\x20\x09]
)|(?:\\(?:\x00|[\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|\x0A|\x0D))))*")))
*))@(?:(?:[A-Za-z0-9!#$%&'*+\-/=?^_`{|}~]+(?:\.[A-Za-z0-9!#$%&'*+\
-/=?^_`{|}~]+)*)|(?:\[(?:[\x21-\x5A\x5E-\x7E]|(?:[\x01-\x08\x0B\x0
C\x0E-\x1F\x7F]|(?:\\(?:[\x21-\x7E]|[\x20\x09])|(?:\\(?:\x00|[\x01
-\x08\x0B\x0C\x0E-\x1F\x7F]|\x0A|\x0D)))))*\])|(?:(?:[A-Za-z0-9!#$
%&'*+\-/=?^_`{|}~]+)(?:\.(?:[A-Za-z0-9!#$%&'*+\-/=?^_`{|}~]+))*))

上記の正規表現を求めるスクリプトは下記の通りです. perl 5.10 で導入された再帰の正規表現は使っていないので, perl 5.8 でも動作します.

my $CR = qq{\\x0D};
my $LF = qq{\\x0A};
my $VCHAR = qq{[\\x21-\\x7E]};
my $WSP = qq{[\\x20\\x09]};

my $obs_NO_WS_CTL = qq{[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]};
my $obs_qtext = $obs_NO_WS_CTL;
my $obs_qp = qq{(?:\\\\(?:\\x00|$obs_NO_WS_CTL|$LF|$CR))};

my $quoted_pair = qq{(?:\\\\(?:$VCHAR|$WSP)|$obs_qp)};

my $atext = qq{[A-Za-z0-9!#\$%&'*+\\-/=?^_`{|}~]};
my $atom = qq{(?:$atext+)};
my $dot_atom_text = qq{(?:$atext+(?:\\.$atext+)*)};
my $dot_atom = $dot_atom_text;

my $qtext = qq{(?:[\\x21\\x23-\\x5B\\x5D-\\x7E]|$obs_qtext)};
my $qcontent = qq{(?:$qtext|$quoted_pair)};
my $quoted_string = qq{(?:"$qcontent*")};

my $obs_dtext = qq{(?:$obs_NO_WS_CTL|$quoted_pair)};
my $dtext = qq{(?:[\\x21-\\x5A\\x5E-\\x7E]|$obs_dtext)};
my $domain_literal = qq{(?:\\[$dtext*\\])};

my $word = qq{(?:$atom|$quoted_string)};
my $obs_local_part = qq{(?:$word(?:\\.$word)*)};
my $obs_domain = qq{(?:$atom(?:\\.$atom)*)};
my $local_part = qq{(?:$dot_atom|$quoted_string|$obs_local_part)};
my $domain = qq{(?:$dot_atom|$domain_literal|$obs_domain)};
my $addr_spec = qq{$local_part\@$domain};
my $mail_regex = $addr_spec;
トップへ

制御文字を除去する

コメントと空白文字を除去する」 で修正したメールアドレスの正規表現ですが,下記の文字列を正しいメールアドレスとして判定してしまいます.下記の文字列には Carol が含まれていますが,制御文字BS(後退)も入っているので,環境によっては表示すると Alice しか見えなくなります.

# "Carol<BS><BS><BS><BS><BS>Alice"@example.com
my $email = qq{"Carol\x08\x08\x08\x08\x08Alice"\@example.com};

"Alice"@example.com

他にもNUL(空文字)やCR(復帰),LF(改行),ESC(エスケープ)などの制御文字を含むことができてしまいます.そこで,制御文字を含まないように,CR,LF, obs-NO-WS-CTLobs-qtextobs-qp として定義されている制御文字を含む部分を除去するように修正した正規表現が 下記のものです.609バイトです.

(?:(?:[A-Za-z0-9!#$%&'*+\-/=?^_`{|}~]+(?:\.[A-Za-z0-9!#$%&'*+\-/=?
^_`{|}~]+)*)|(?:"(?:[\x21\x23-\x5B\x5D-\x7E]|(?:\\(?:[\x21-\x7E]|[
\x20\x09])))*")|(?:(?:(?:[A-Za-z0-9!#$%&'*+\-/=?^_`{|}~]+)|(?:"(?:
[\x21\x23-\x5B\x5D-\x7E]|(?:\\(?:[\x21-\x7E]|[\x20\x09])))*"))(?:\
.(?:(?:[A-Za-z0-9!#$%&'*+\-/=?^_`{|}~]+)|(?:"(?:[\x21\x23-\x5B\x5D
-\x7E]|(?:\\(?:[\x21-\x7E]|[\x20\x09])))*")))*))@(?:(?:[A-Za-z0-9!
#$%&'*+\-/=?^_`{|}~]+(?:\.[A-Za-z0-9!#$%&'*+\-/=?^_`{|}~]+)*)|(?:\
[(?:[\x21-\x5A\x5E-\x7E]|(?:\\(?:[\x21-\x7E]|[\x20\x09])))*\])|(?:
(?:[A-Za-z0-9!#$%&'*+\-/=?^_`{|}~]+)(?:\.(?:[A-Za-z0-9!#$%&'*+\-/=
?^_`{|}~]+))*))

上記の正規表現を求めるスクリプトは下記の通りです.

my $VCHAR = qq{[\\x21-\\x7E]};
my $WSP = qq{[\\x20\\x09]};

my $quoted_pair = qq{(?:\\\\(?:$VCHAR|$WSP))};

my $atext = qq{[A-Za-z0-9!#\$%&'*+\\-/=?^_`{|}~]};
my $atom = qq{(?:$atext+)};
my $dot_atom_text = qq{(?:$atext+(?:\\.$atext+)*)};
my $dot_atom = $dot_atom_text;

my $qtext = qq{[\\x21\\x23-\\x5B\\x5D-\\x7E]};
my $qcontent = qq{(?:$qtext|$quoted_pair)};
my $quoted_string = qq{(?:"$qcontent*")};

my $obs_dtext = $quoted_pair;
my $dtext = qq{(?:[\\x21-\\x5A\\x5E-\\x7E]|$obs_dtext)};
my $domain_literal = qq{(?:\\[$dtext*\\])};

my $word = qq{(?:$atom|$quoted_string)};
my $obs_local_part = qq{(?:$word(?:\\.$word)*)};
my $obs_domain = qq{(?:$atom(?:\\.$atom)*)};
my $local_part = qq{(?:$dot_atom|$quoted_string|$obs_local_part)};
my $domain = qq{(?:$dot_atom|$domain_literal|$obs_domain)};
my $addr_spec = qq{$local_part\@$domain};
my $mail_regex = $addr_spec;
トップへ

IPアドレスを除去する

制御文字を除去する」 で修正したメールアドレスの正規表現ですが, 下記の文字列を正しいメールアドレスとして判定してしまいます.

# foo@[192.0.2.123]
my $email = q{foo@[192.0.2.123]};

foo@[192.0.2.123]

上記の文字列は domain-literal として定義されている部分を含むように 作成した文字列です.domain-literal については, RFC 5321( 日本語訳 ) で address-literal として定義されています. address-literal はIPv4アドレスやIPv6アドレスで 宛先ホストを指定するために使用されます. しかし domain-literal を含むメールアドレスは, 正しいメールアドレスとしては判定してほしくない場合がほとんどでしょう. そこで,domain-literal を含まないように修正した正規表現が下記のものです. 542バイトです.

(?:(?:[A-Za-z0-9!#$%&'*+\-/=?^_`{|}~]+(?:\.[A-Za-z0-9!#$%&'*+\-/=?
^_`{|}~]+)*)|(?:"(?:[\x21\x23-\x5B\x5D-\x7E]|(?:\\(?:[\x21-\x7E]|[
\x20\x09])))*")|(?:(?:(?:[A-Za-z0-9!#$%&'*+\-/=?^_`{|}~]+)|(?:"(?:
[\x21\x23-\x5B\x5D-\x7E]|(?:\\(?:[\x21-\x7E]|[\x20\x09])))*"))(?:\
.(?:(?:[A-Za-z0-9!#$%&'*+\-/=?^_`{|}~]+)|(?:"(?:[\x21\x23-\x5B\x5D
-\x7E]|(?:\\(?:[\x21-\x7E]|[\x20\x09])))*")))*))@(?:(?:[A-Za-z0-9!
#$%&'*+\-/=?^_`{|}~]+(?:\.[A-Za-z0-9!#$%&'*+\-/=?^_`{|}~]+)*)|(?:(
?:[A-Za-z0-9!#$%&'*+\-/=?^_`{|}~]+)(?:\.(?:[A-Za-z0-9!#$%&'*+\-/=?
^_`{|}~]+))*))

上記の正規表現を求めるスクリプトは下記の通りです.

my $VCHAR = qq{[\\x21-\\x7E]};
my $WSP = qq{[\\x20\\x09]};

my $quoted_pair = qq{(?:\\\\(?:$VCHAR|$WSP))};

my $atext = qq{[A-Za-z0-9!#\$%&'*+\\-/=?^_`{|}~]};
my $atom = qq{(?:$atext+)};
my $dot_atom_text = qq{(?:$atext+(?:\\.$atext+)*)};
my $dot_atom = $dot_atom_text;

my $qtext = qq{[\\x21\\x23-\\x5B\\x5D-\\x7E]};
my $qcontent = qq{(?:$qtext|$quoted_pair)};
my $quoted_string = qq{(?:"$qcontent*")};

my $word = qq{(?:$atom|$quoted_string)};
my $obs_local_part = qq{(?:$word(?:\\.$word)*)};
my $obs_domain = qq{(?:$atom(?:\\.$atom)*)};
my $local_part = qq{(?:$dot_atom|$quoted_string|$obs_local_part)};
my $domain = qq{(?:$dot_atom|$obs_domain)};
my $addr_spec = qq{$local_part\@$domain};
my $mail_regex = $addr_spec;
トップへ

旧形式を除去する

IPアドレスを除去する」 までで修正してきたメールアドレスの正規表現ですが, 旧形式を含むメールアドレスの正規表現でした.旧形式というのは RFC 822( 日本語訳 ) で定義されているもので, RFC 2822( 日本語訳 ) の時点で obsolete となりました. 旧形式の部分の正規表現は $obs_ で始まる変数で表現しています. 旧形式のメールアドレスを正しいと判定することは, 過去との互換のためには必要といえます. しかし,今後は旧形式のメールアドレスを正しいと判定する必要はないでしょう.

IPアドレスを除去する」 で修正したメールアドレスの正規表現に残っている旧形式の部分は $obs_domain$obs_local_part です. しかし,実は $obs_domain$dot_atom と同じ意味の正規表現になります. $domain$dot_atom$obs_domain の論理和で定義されていましたが, 両者は同じ意味の正規表現なので,$obs_domain の方は不要だったわけです. 残る $obs_local_part の部分を含むように作成したメールアドレスが下記の文字列になります.

# "foo"."bar"@example.com
my $email = q{"foo"."bar"@example.com};

"foo"."bar"@example.com

旧形式では local-part部分にダブルクォートで囲む表現(quoted-string)を, ピリオド(.)でつなげて複数使うことができました. しかし,新形式では local-part部分全体がダブルクォートで囲む表現 (quoted-string)である以外は使うことができなくなりました. 元々不要だった obs-domain と,旧形式の obs-local-part を含まないように 修正した正規表現が下記のものです.224バイトです.

(?:(?:[A-Za-z0-9!#$%&'*+\-/=?^_`{|}~]+(?:\.[A-Za-z0-9!#$%&'*+\-/=?
^_`{|}~]+)*)|(?:"(?:[\x21\x23-\x5B\x5D-\x7E]|(?:\\(?:[\x21-\x7E]|[
\x20\x09])))*"))@(?:[A-Za-z0-9!#$%&'*+\-/=?^_`{|}~]+(?:\.[A-Za-z0-
9!#$%&'*+\-/=?^_`{|}~]+)*)

上記の正規表現を求めるスクリプトは下記の通りです.

my $VCHAR = qq{[\\x21-\\x7E]};
my $WSP = qq{[\\x20\\x09]};

my $quoted_pair = qq{(?:\\\\(?:$VCHAR|$WSP))};

my $atext = qq{[A-Za-z0-9!#\$%&'*+\\-/=?^_`{|}~]};
my $dot_atom_text = qq{(?:$atext+(?:\\.$atext+)*)};
my $dot_atom = $dot_atom_text;

my $qtext = qq{[\\x21\\x23-\\x5B\\x5D-\\x7E]};
my $qcontent = qq{(?:$qtext|$quoted_pair)};
my $quoted_string = qq{(?:"$qcontent*")};

my $local_part = qq{(?:$dot_atom|$quoted_string)};
my $domain = $dot_atom;
my $addr_spec = qq{$local_part\@$domain};
my $mail_regex = $addr_spec;
トップへ

正規表現を簡略化する

旧形式を除去する」 で修正したメールアドレスの正規表現ですが, 書き方を工夫することでもっと短くすることができます. 短くすることで効率的になる面もありますが,逆に可読性が悪くなる面もあるため, 何でもかんでも短くすることがよいとは限りません. ここでは単純に短くすることを考えます.

my $VCHAR = qq{[\\x21-\\x7E]};
my $WSP = qq{[\\x20\\x09]};
my $quoted_pair = qq{(?:\\\\(?:$VCHAR|$WSP))};
  ↓
my $quoted_pair = qq{(?:\\\\[\\x09\\x20-\\x7E])};

上記のように,文字クラス同士の論理和は1つにまとめることができます.

my $quoted_pair = qq{(?:\\\\[\\x09\\x20-\\x7E])};
  ↓
my $quoted_pair = qq{(?:\\\\[\\x09 -~])};

my $atext = qq{[A-Za-z0-9!#\$%&'*+\\-/=?^_`{|}~]};
  ↓
my $atext = qq{[-!#-'*+/-9=?A-Z^-~]};

my $qtext = qq{[\\x21\\x23-\\x5B\\x5D-\\x7E]};
  ↓
my $qtext = qq{[!#-\\[\\]-~]};

上記のように,文字クラスの中身を書き換えることができます. 16進数で記述していた部分は該当する文字に書き換えました. 更に,ASCII順に注意しながら可能な限り範囲指定を使って書き換えました. また,マイナス(-)そのものは文字クラス内の先頭に置くことで, エスケープしなくても良いようにしています.

my $quoted_pair = qq{(?:\\\\[\\x09 -~])};
  ↓
my $quoted_pair = qq{\\\\[\\x09 -~]};

my $dot_atom_text = qq{(?:$atext+(?:\\.$atext+)*)};
  ↓
my $dot_atom_text = qq{$atext+(?:\\.$atext+)*};

my $quoted_string = qq{(?:"$qcontent*")};
  ↓
my $quoted_string = qq{"$qcontent*"};

上記のように,冗長なクラスタ((?:pattern))を削除することができます. 元々,RFCに準拠したメールアドレスの正規表現 を作成するとき,各変数ごとに量指定子(*や+など)を後ろに付けたときに, 意図したとおりに動作するようにクラスタ化をしてありました. 例えば,$word = 'word'; と定義すると, $words = qq{$word+}; のように書いたときに, マッチするのは wordddd... となってしまいます. このようにならないように $word = '(?:word)'; のようにクラスタ化して定義しているということです. このため,最終的にクラスタ化する必要がないと判明したものは 削除することができます.

上記の修正をまとめると下記のようになります.

my $quoted_pair = qq{\\\\[\\x09 -~]};

my $atext = qq{[-!#-'*+/-9=?A-Z^-~]};
my $dot_atom_text = qq{$atext+(?:\\.$atext+)*};
my $dot_atom = $dot_atom_text;

my $qtext = qq{[!#-\\[\\]-~]};
my $qcontent = qq{(?:$qtext|$quoted_pair)};
my $quoted_string = qq{"$qcontent*"};

my $local_part = qq{(?:$dot_atom|$quoted_string)};
my $domain = $dot_atom;
my $addr_spec = qq{$local_part\@$domain};
my $mail_regex = $addr_spec;

上記の修正をした正規表現が下記のものです. 134バイトとなりました.

(?:[-!#-'*+/-9=?A-Z^-~]+(?:\.[-!#-'*+/-9=?A-Z^-~]+)*|"(?:[!#-\[\]-
~]|\\[\x09 -~])*")@[-!#-'*+/-9=?A-Z^-~]+(?:\.[-!#-'*+/-9=?A-Z^-~]+
)*

以下がこれを直接代入して使うスクリプトになります.

my $mail_regex =
q{(?:[-!#-'*+/-9=?A-Z^-~]+(?:\.[-!#-'*+/-9=?A-Z^-~]+)*|"(?:[!#-\[\]-} .
q{~]|\\\\[\x09 -~])*")@[-!#-'*+/-9=?A-Z^-~]+(?:\.[-!#-'*+/-9=?A-Z^-~]+} .
q{)*};
トップへ

参考文献

トップへ
戻る
うずら メール

Copyright (C) 2009-2019 OHZAKI Hiroki. All rights reserved.