$atext
のバグ修正トップへメールアドレスについては
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 が正しいメールアドレス(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-CTL ,obs-qtext ,obs-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;
トップへ「制御文字を除去する」 で修正したメールアドレスの正規表現ですが, 下記の文字列を正しいメールアドレスとして判定してしまいます.
# 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';
のように書いたときに, マッチするのは wordddd... となってしまいます. このようにならないように $words = qq{$word+};
のようにクラスタ化して定義しているということです. このため,最終的にクラスタ化する必要がないと判明したものは 削除することができます. $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{)*};
トップへ
- RFC 5322: Internet Message Format
- RFC 5321: Simple Mail Transfer Protocol / 日本語訳
- メールアドレス - Wikipedia
- メールアドレス変更 | お知らせ | NTTドコモ
- メールアドレス変更方法 | 迷惑Eメール防止方法 | au