为啥 jQuery 的电子邮件验证正则表达式如此简单?
Posted
技术标签:
【中文标题】为啥 jQuery 的电子邮件验证正则表达式如此简单?【英文标题】:Why is jQuery's email validation regex so simple?为什么 jQuery 的电子邮件验证正则表达式如此简单? 【发布时间】:2011-05-18 06:15:35 【问题描述】:我们都知道正确验证电子邮件的正则表达式是quite complicated。然而,jQuery 的验证插件有一个较短的正则表达式 (由Scott Gonzalez 提供),只跨越几行:
/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`\|~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])
+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`\|~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|
((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|
[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]
|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?
(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|
[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*
([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|
[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])
([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|
[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/
与更知名的怪物相比,为什么它如此“简单”?是否存在一个正则表达式失败而另一个成功的情况(这些案例是有效的还是无效的电子邮件)?
【问题讨论】:
简单不是我用于该正则表达式的词;) 咳咳 简单吗?如果该正则表达式很简单,您会将什么归类为复杂? 谈谈涉足只写语言领域... @Alex:查看我在问题中的第一个链接... 【参考方案1】:正则表达式是以下的自定义组合:
RFC 2234 ABNF RFC 2396 URI 通用语法(被 RFC 3986 淘汰) RFC 2616 超文本传输协议 -- HTTP/1.1 RFC 2822 互联网消息格式 RFC 3987 IRI RFC 3986 URI 通用语法我在起草 Web Forms 2.0 并且 RFC 5322 不存在时编写了正则表达式。如果您查看 RFC 的编写顺序,您会注意到 IRI 和 URI 的定义在编写 Internet 消息格式后发生了变化。这意味着 RFC 2822 不支持当前的 IRI 定义。不幸的是,仅替换定义并不是一项简单的任务,因此我必须从 RFC 中挑选要使用的定义。我还选择了要删除的内容(例如对 cmets 的支持)。
正则表达式不是完全手写的。虽然我确实手动编写了正则表达式的每个部分,但我编写了“胶水”脚本。 RFC 中的每个定义都存储在一个变量中,复合定义利用存储更简单定义的变量(@Walf:这就是为什么有这么多子模式和 ors)。
更复杂的是,jQuery Validation 插件中使用的正则表达式版本被进一步修改,以解决规范有效地址和用户对有效地址的期望之间的差异。我不记得我做了什么修改。我向 Jörn Zaefferer(验证插件的作者)承诺,我会编写一个更新的脚本来生成正则表达式。新脚本将允许您为您支持和不想支持的内容指定选项(必需的 TLD、特定的 TLD、IPv6、cmets、过时的定义、引用的本地名称等)。那是5年前的事了。我开始了一次,但从未完成。也许有一天我会的。我目前所拥有的托管在 GitHub 上:https://github.com/scottgonzalez/regex-builder
如果您想要一个用于验证电子邮件地址的正则表达式,我建议您使用 html5 specification 中包含的以下正则表达式:
/^[a-zA-Z0-9.!#$%&'*+/=?^_`|~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]0,61[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]0,61[a-zA-Z0-9])?)*$/
如果您使用 regex-builder 并关闭所有选项,您会得到类似的结果。但是自从我看到它以来已经大约一年了,所以我不记得有什么不同。
我还想指出,原始问题中的链接特别提到了 RFC 822。虽然 RFC 822 将我们从 Arpanet 推进到 ARPA Internet,这很棒,但这并不是最新的。在过去的三年中,Internet 取得了一些进步,并且该 RFC 已被两次取代。我希望看到任何符合最新标准的新作品。
更新:
一位朋友问我为什么 HTML5 正则表达式不支持 UTF-8。我从来没有问过 Hixie,但我认为这就是原因:尽管一些 TLD 在 2000 年开始支持 IDN(国际域名)并且 RFC 3987 (IRI) 是在 2005 年编写的,而 RFC 5322 是在 2008 年编写的它仅将 33-90 和 94-126 范围内的字符列为有效 dtext(允许在域文字中使用的字符)。 HTML5 基于 RFC 5322,因此不支持 UTF-8。 RFC 5322 不考虑 IDN 确实看起来很奇怪,但即使在 2008 年 IDN 也实际上不可用,这毫无价值。直到 2010 年 ICANN 才批准了第一组 IDN。但是,即使在今天,如果您想使用 IDN,如果您确实希望电子邮件和 DNS 之类的东西在全球范围内工作,您几乎需要使用 Punycode 完全销毁您的域名。
更新 2:
更新了 HTML5 正则表达式以匹配更新后的规范,将标签长度限制从 255 个字符更改为 63 个字符,如 RFC 1034 section 3.5 中所指定。
【讨论】:
HTML5 规范页面的版本与此模式略有不同;也许它已经更新了?主要是将部分限制为 63 个(在 RFC 中称为标签)。它还可以防止以连字符结束标签。 由于堆栈和***一直相互引用,我在这里找到了一些很好的总结:blog.sacaluta.com/2011/12/… 和 blogs.msdn.com/b/oldnewthing/archive/2012/04/12/10292868.aspx @goodeye 感谢您指出这一点。我已经更新了正则表达式,虽然标签结尾没有变化,只是长度。 谢谢 - 是的,我看到你已经处理了结局。这是我们将用于电子邮件验证的一个很好的模式。【参考方案2】:看起来不对:Unicode 是怎么回事?这是针对哪个 RFC 进行验证的?
有关正确的 RFC5322 验证正则表达式,请参阅 this answer。
【讨论】:
我也觉得不合适;因此问题。这直接取自标记为$Id: jquery.validate.js 6403 2009-06-17 14:27:16Z joern.zaefferer $
1011 行的文件。以上是关于为啥 jQuery 的电子邮件验证正则表达式如此简单?的主要内容,如果未能解决你的问题,请参考以下文章
jquery正则表达式验证是否带有小数是否中文名称组成是否全由8位数字组成电话码格式邮件地址