【问题标题】:fully RFC5321- and 5322-compatible PHP PCRE regex完全兼容 RFC5321 和 5322 的 PHP PCRE 正则表达式
【发布时间】:2019-05-02 22:49:41
【问题描述】:

我正在尝试创建一个(几乎)与 RFC5321 和 5322 完全兼容的 PHP PCRE 正则表达式来测试 email addresses。我唯一不需要的是(评论)部分。我在这里看到了一些其他的尝试,但是当我对它们进行测试时,它们并不都有效。

我一直在研究一个非常接近的:

 ^(([\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(它不会检查以确保它们是

   (\[\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}\])

)

它唯一缺少的是能够检查多个连续的 . (句点)在引用的本地部分之外。我使用我自己的一些测试和wikipedia article about email addresses 上的测试对regex101.com 与以下所有地址进行了测试:

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

我尝试使用前瞻和后瞻断言来测试连续的周期,但我无法弄清楚。我认为这是它唯一缺少的东西(除了 cmets,出于我的目的,这不是必需的)。

有没有办法检查不会改变我目前拥有太多东西的时期,还是需要不同的方法?

如果我错过了任何其他内容,请告诉我。

谢谢。

【问题讨论】:

标签: php regex email pcre


【解决方案1】:

我会推荐你​​read this。可以说,编写一个 100% 有效的正则表达式是不可能的。

我写了一个非正则表达式实现here。如果您将此移植到 php 并在我的 github 页面上提交问题或给我发送电子邮件(在我的 github 页面上列出),我会很乐意链接到它。

unit tests 可以看出,它的全面性也足以与 EAI 地址一起使用。

【讨论】:

  • 我认为现实可能比我想象的要困难得多。我认为最困难的部分是处理 EAI 的东西。感谢您提供这些文章和信息!
【解决方案2】:

您可以在^ 之后添加(?!("[^"]*"|[^"])*\.{2})

请参阅regex demo

(?!("[^"]*"|[^"])*\.{2}) 否定前瞻失败匹配,如果紧靠当前位置的右侧有

  • ("[^"]*"|[^"])* - 0 次或多次出现 ",后跟 0+ 个除 " 以外的字符,然后是 " 或除 " 以外的任何字符
  • \.{2} - 两个连续的点。

【讨论】:

    猜你喜欢
    • 2011-10-27
    • 1970-01-01
    • 1970-01-01
    • 2014-08-02
    • 2017-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多