【问题标题】:What's wrong with this RegEx for validating emails?这个用于验证电子邮件的 RegEx 有什么问题?
【发布时间】:2010-11-07 18:35:30
【问题描述】:

这是一个用于验证电子邮件的正则表达式 - \S+@\S+\.\S+,不是我写的。我是正则表达式的新手,不太了解它们。

我有几个问题:

  1. 上面的 RegEx 有什么问题
  2. 什么是 RegEx 验证电子邮件?

【问题讨论】:

  • 谁想成为第一个发布三页电子邮件正则表达式的人?
  • 至于它有什么问题:嗯,一方面,它不允许在第一部分出现点。这将使我的三个电子邮件地址中的两个失去资格。此外,它仅允许在第二部分中使用一个点,这将取消诸如“.co.uk”之类的域的资格。
  • 它也不允许在用户名中使用“+”号,这是合法的。 “+”号后面的部分被忽略,但很多人用它来过滤电子邮件。例如,给定用户名“user@gmail.com”,有人可能会使用“user+amazon@gmail.com”作为亚马逊电子邮件,从而允许他们轻松过滤邮件(或跟踪特定服务是否将他们的电子邮件地址提供给另一项服务)。
  • 什么意思,不允许? \S 匹配任何个非空白字符。
  • 的确,艾伦是对的。 mipadimmyers,你们都错了:\S 匹配 .(点)和 +

标签: regex email-validation


【解决方案1】:

“我如何使用正则表达式验证电子邮件”是涉及正则表达式时出现的更受欢迎的问题之一,唯一真正好的答案是“你不需要”。它已经在这个网站上讨论过inmanyoccasions。您必须了解的是,如果您真的想遵循规范,您的正则表达式将类似于this。显然,这是一个怪物,更像是一种练习,以证明坚持你应该能够接受的事情是多么可笑的困难。考虑到这一点,如果您绝对需要知道电子邮件地址是否有效,唯一真正的检查方法是实际向该电子邮件地址发送一条消息并检查它是否被退回。否则,this regex 将正确验证大多数情况,并且在很多情况下大多数情况就足够了。此外,该页面将讨论尝试使用正则表达式验证电子邮件的问题。

【讨论】:

    【解决方案2】:

    我只会从技术正则表达式的角度回答您的第一个问题

    正则表达式\S+@\S+\.\S+ 的问题在于它有可能执行得太慢。如果有人输入了如下所示的电子邮件字符串,并且您需要对其进行验证,会发生什么情况?

    a@b.cdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789

    甚至更糟(是的,点后有 100 个 @):

    @.@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@\@@@@@@@@@@@@@@@@@@@@@@@@@@\@@@@@@@@@@@@@@@@@ @@@@@@@@

    缓慢发生。首先,正则表达式会贪婪地为第一个\S+ 匹配尽可能多的字符。因此,它最初会匹配整个字符串。然后我们需要@ 字符,所以它会回溯直到找到一个。那时我们有另一个\S+,所以,它会再次消耗所有内容,直到字符串结束。然后它需要再次回溯,直到找到一个点。你能想象在正则表达式最终在第二个电子邮件字符串上失败之前发生了多少回溯吗?

    为了消除回溯,我建议在这种情况下使用所有格字符类,它的另一个好处是不允许在一个字符串中使用多个@。

    [^@\s]++@[^@\s.]++\.[^@\s]++

    我针对“100 @'s email”对这两个正则表达式进行了快速基准测试。我的大约快 95 倍。

    【讨论】:

    • 嗨 Geert,很高兴在这里见到你。关于正则表达式的执行时间:在这种情况下,我认为这并不重要,除非您要在很短的时间内验证数千个地址,或者地址有数千个字符长。 (但我们之前讨论过 :))问候,巴特(prometheuzz)。
    • 我想知道许可正则表达式比巨大的 RFC 正则表达式慢多少,我猜它仍然比这快得多,所以在这种情况下,性能似乎不是一个主要问题.本质上,比 1 毫秒慢 95 倍,也就是 95 毫秒,可以忽略不计。那么我们在这里谈论的是哪种减速?
    【解决方案3】:

    上面的 RegEx 有什么问题?

    它只检查 '@' 和 . 有很多东西绝对不是与该组合匹配的合法电子邮件地址。

    例如,如果一个人写了 user@www.myWebsite.com 它会匹配,但这显然是一个错误。在正则表达式中稍微复杂一点会抓住它并帮助用户。

    如果他输入 user@myWebsite.nt 也是如此——他拼错了“net”。或者他输入两个@@(user@@yahoo.com / user@yahoo@yahoo.com - 这实际上很常见),或者两个点(user@yahoo..com)。更好的正则表达式应该能捕捉到这些。

    [虽然更好的检查通常会因其他错误而停止,例如在“at”前后的合法多个点可能会被删除或失效 (my.name@gmail.com)]

    如果你不想挑剔,你甚至不需要正则表达式。 indexOf('@') != -1 将捕获大部分错误。一旦检查,你应该做得更好。

    什么是验证电子邮件的好 RegEx?

    http://www.gooli.org/blog/useful-regular-expressions

    http://www.regular-expressions.info/email.html

    【讨论】:

    • user@www.myWebsite.com 是一个有效的电子邮件地址。
    • 真的吗?!如果我做 myName@www.yahoo.com 我会得到它吗?虽然现在我想起来,以 .nt 结尾的东西在技术上可能也是。捕获并验证以上两个仍然是正确的。
    • 在一封电子邮件的后半部分有多个点是很常见的,例如 johnny@corporate.example.com
    【解决方案4】:

    我看到@liam 发布了a link to the RFC822。但是,按照 stackoverflow 是一个目的地的想法,如果 ex-parrot.com 删除了链接,或者你有什么。在它的整个...

    Mail::RFC822::Address: 基于正则表达式的地址验证

    Mail::RFC822::Address 是一个 Perl 模块,用于根据 RFC 822 grammar 验证电子邮件地址。它提供与 RFC::RFC822::Address 相同的功能,但使用 Perl 正则表达式而不是 Parse::RecDescent 解析器。这意味着模块的加载速度要快得多,因为它不需要在启动时编译语法。

    下载Mail::RFC822::Address-0.4.tar.gzread the documentation

    RFC 822 中描述的语法非常复杂。使用正则表达式实现验证在某种程度上推动了使用正则表达式的合理范围,尽管 Perl 可以很好地应对:

    (?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]
    )+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:
    \r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(
    ?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ 
    \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\0
    31]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\
    ](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+
    (?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:
    (?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z
    |(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)
    ?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\
    r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[
     \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)
    ?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t]
    )*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[
     \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*
    )(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]
    )+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)
    *:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+
    |\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r
    \n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
    \r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t
    ]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031
    ]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](
    ?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?
    :(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?
    :\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?
    :(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?
    [ \t]))*"(?:(?:\r\n)?[ \t])*)*:(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] 
    \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|
    \\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>
    @,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"
    (?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t]
    )*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
    ".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?
    :[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[
    \]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-
    \031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(
    ?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;
    :\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([
    ^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\"
    .\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\
    ]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\
    [\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\
    r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] 
    \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]
    |\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \0
    00-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\
    .|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,
    ;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?
    :[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*
    (?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".
    \[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[
    ^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]
    ]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)(?:,\s*(
    ?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
    ".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(
    ?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[
    \["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t
    ])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t
    ])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?
    :\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|
    \Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:
    [^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\
    ]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)
    ?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["
    ()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)
    ?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>
    @,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[
     \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,
    ;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t]
    )*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
    ".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?
    (?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".
    \[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:
    \r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\[
    "()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])
    *))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])
    +|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\
    .(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z
    |(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(
    ?:\r\n)?[ \t])*))*)?;\s*)
    

    此正则表达式将仅验证已删除任何 cmets 并替换为空格的地址(这是由模块完成的)。

    【讨论】:

      【解决方案5】:

      上面的 RegEx 有什么问题?
      电子邮件地址的 RFC822 标准非常松散,因此很难找到一个简洁的正则表达式来捕获所有可能的有效电子邮件。由于并非每个邮件服务器/客户端都执行此标准,因此问题变得复杂,因此实际数据可能是

      虽然您当然可以猜测或强制执行特定格式,但编写临时表达式几乎可以保证您将拥有大量垃圾电子邮件地址或拒绝有效的电子邮件地址。

      什么是验证电子邮件的好 RegEx?
      这是针对 RFC 进行验证的参考正则表达式,它在此处作为 perl 模块实现,但也是 O'Reillys “掌握正则表达式”中的最终列表

      Mail::RFC822::Address

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-07-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-27
        • 2018-12-22
        • 2019-06-16
        相关资源
        最近更新 更多