完全兼容 RFC5321 和 5322 PHP PCRE 正则表达式
fully RFC5321- and 5322-compatible PHP PCRE regex
我正在尝试创建一个(几乎)与 RFC5321 和 5322 完全兼容的 PHP PCRE 正则表达式来测试 email addresses。我唯一不需要的是 (comment) 部分。我已经在此处看到其他一些尝试,但是当我 运行 测试它们时,它们并不都有效。
我一直在研究一个非常接近的:
^(([\w \!\#$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~\.]{1,64})|("[\w \!\#$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~\.]{1,64}"))@(([\w\-]*\.?[\w\-]*)|(\[\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}\])|(\[IPv6:[\da-fA-F]{0,4}:[\da-fA-F]{0,4}:[\da-fA-F]{0,4}:[\da-fA-F]{0,4}\]))$
分解:
本地部分:
(
最多匹配 64 个允许的字符
([\w \!\#$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~\.]{1,64})
|
或匹配带引号的字符串中的同一组字符:
("[\w \!\#$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~\.]{1,64}")
)
结束本地部分。
匹配@符号
@
匹配域部分:
(
使用允许的字符匹配域部分:
([\w\-]*\.?[\w\-]*)
或 ipv4(它不会检查以确保它们小于 255 - 这将在别处处理)
(\[\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}\])
或 ipv6
(\[IPv6:[\da-fA-F]{0,4}:[\da-fA-F]{0,4}:[\da-fA-F]{0,4}:[\da-fA-F]{0,4}\])
)
它唯一缺少的是检查在引用的本地部分之外的多个连续的 .(句点)的能力。我 运行 测试 regex101.com vs. all the addresses below using some of my own tests and the tests on the wikipedia article about email addresses:
bob@smith.com
bob.smith@smith.com
bob-smith@smith.com
bob-smith@bob-smith.com
b0b!-...smith@smith.com <-DOES NOT VALIDATE CORRECTLY - MULTIPLE .'s
bob&smith@smith.com
"bob..smith"@smith.com
simple@example.com
very.common@example.com
disposable.style.email.with+symbol@example.com
other.email-with-hyphen@example.com
fully-qualified-domain@example.com
user.name+tag+sorting@example.com
x@example.com
example-indeed@strange-example.com
admin@mailserver1
example@s.example
" "@example.org
"john..doe"@example.org
Abc.example.com
A@b@c@example.com
a"b(c)d,e:f;g<h>i[j\k]l@example.com
just"not"right@example.com
this is"not\allowed@example.com
this\ still\"not\allowed@example.com
1234567890123456789012345678901234567890123456789012345678901234+x@example.com
john..doe@example.com <-DOES NOT VALIDATE CORRECTLY - MULTIPLE .'s
john.doe@example..com
我试图使用先行断言和后行断言来测试连续的时间段,但我无法弄清楚。我认为这是它唯一缺少的东西(除了评论,就我的目的而言,评论不是必需的)。
有没有一种方法可以检查不会改变我目前拥有太多东西的时期,或者是否需要不同的方法?
如果我遗漏了什么,请告诉我。
谢谢。
我会推荐你 read this。可以这么说,编写一个 100% 有效的正则表达式是不可能的。
我写了一个非 Regex 实现 here。如果您将其移植到 php 并在我的 github 页面上提交问题或给我发送电子邮件(列在我的 github 页面上),我会很乐意 link 给它。
从 unit tests 中可以看出,它足够全面,也可以使用 EAI 地址。
您可以在 ^
之后添加 (?!("[^"]*"|[^"])*\.{2})
。
参见regex demo。
如果紧挨着当前位置的右侧有
,则(?!("[^"]*"|[^"])*\.{2})
否定先行匹配失败
("[^"]*"|[^"])*
- "
出现 0 次或多次,后跟 "
以外的 0+ 个字符,然后是 "
或 [=14= 以外的任何字符]
\.{2}
- 两个连续的点。
我正在尝试创建一个(几乎)与 RFC5321 和 5322 完全兼容的 PHP PCRE 正则表达式来测试 email addresses。我唯一不需要的是 (comment) 部分。我已经在此处看到其他一些尝试,但是当我 运行 测试它们时,它们并不都有效。
我一直在研究一个非常接近的:
^(([\w \!\#$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~\.]{1,64})|("[\w \!\#$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~\.]{1,64}"))@(([\w\-]*\.?[\w\-]*)|(\[\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}\])|(\[IPv6:[\da-fA-F]{0,4}:[\da-fA-F]{0,4}:[\da-fA-F]{0,4}:[\da-fA-F]{0,4}\]))$
分解:
本地部分:
(
最多匹配 64 个允许的字符
([\w \!\#$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~\.]{1,64})
|
或匹配带引号的字符串中的同一组字符:
("[\w \!\#$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~\.]{1,64}")
)
结束本地部分。
匹配@符号
@
匹配域部分:
(
使用允许的字符匹配域部分:
([\w\-]*\.?[\w\-]*)
或 ipv4(它不会检查以确保它们小于 255 - 这将在别处处理)
(\[\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}\])
或 ipv6
(\[IPv6:[\da-fA-F]{0,4}:[\da-fA-F]{0,4}:[\da-fA-F]{0,4}:[\da-fA-F]{0,4}\])
)
它唯一缺少的是检查在引用的本地部分之外的多个连续的 .(句点)的能力。我 运行 测试 regex101.com vs. all the addresses below using some of my own tests and the tests on the wikipedia article about email addresses:
bob@smith.com
bob.smith@smith.com
bob-smith@smith.com
bob-smith@bob-smith.com
b0b!-...smith@smith.com <-DOES NOT VALIDATE CORRECTLY - MULTIPLE .'s
bob&smith@smith.com
"bob..smith"@smith.com
simple@example.com
very.common@example.com
disposable.style.email.with+symbol@example.com
other.email-with-hyphen@example.com
fully-qualified-domain@example.com
user.name+tag+sorting@example.com
x@example.com
example-indeed@strange-example.com
admin@mailserver1
example@s.example
" "@example.org
"john..doe"@example.org
Abc.example.com
A@b@c@example.com
a"b(c)d,e:f;g<h>i[j\k]l@example.com
just"not"right@example.com
this is"not\allowed@example.com
this\ still\"not\allowed@example.com
1234567890123456789012345678901234567890123456789012345678901234+x@example.com
john..doe@example.com <-DOES NOT VALIDATE CORRECTLY - MULTIPLE .'s
john.doe@example..com
我试图使用先行断言和后行断言来测试连续的时间段,但我无法弄清楚。我认为这是它唯一缺少的东西(除了评论,就我的目的而言,评论不是必需的)。
有没有一种方法可以检查不会改变我目前拥有太多东西的时期,或者是否需要不同的方法?
如果我遗漏了什么,请告诉我。
谢谢。
我会推荐你 read this。可以这么说,编写一个 100% 有效的正则表达式是不可能的。
我写了一个非 Regex 实现 here。如果您将其移植到 php 并在我的 github 页面上提交问题或给我发送电子邮件(列在我的 github 页面上),我会很乐意 link 给它。
从 unit tests 中可以看出,它足够全面,也可以使用 EAI 地址。
您可以在 ^
之后添加 (?!("[^"]*"|[^"])*\.{2})
。
参见regex demo。
如果紧挨着当前位置的右侧有
,则(?!("[^"]*"|[^"])*\.{2})
否定先行匹配失败
("[^"]*"|[^"])*
-"
出现 0 次或多次,后跟"
以外的 0+ 个字符,然后是"
或 [=14= 以外的任何字符]\.{2}
- 两个连续的点。