0

我正在调试一个应用程序中的一个问题,该应用程序使用正则表达式来验证电子邮件客户端(是的,我知道,两者都有点愚蠢),这个问题让我非常难过。

问题是验证在 Chrome 中工作得很好,但在 Firefox 中失败,我想知道这是一个错误,还是导致错误的正则表达式有问题。

请检查此小提琴以获取完整的测试用例:http: //jsfiddle.net/KQvgJ/

new RegExp(/^\S+([\_\-\.]*\S+[\_\-]?)*@\S+([\_\-]?\S+)*\.+([\-\_]?\S)+(\.?\S+)*$/);

在 Firefox 中,只有上面的正则表达式匹配mw@thisissometest.de,但不匹配mw@thisissometestbutlong.de.

仅根据输入的长度似乎失败了,但是表达式中根本没有长度限制!?

4

2 回答 2

3

改进概念

首先,让我们明确一点,\S+它将匹配任何不是空白的东西一次或多次。

^\S+([\_\-\.]*\S+[\_\-]?)*@\S+([\_\-]?\S+)*\.+([\-\_]?\S)+(\.?\S+)*$
    ^^^^^^^^^^^^^^^^^^^^^^    ^^^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^
    This all get's matched     Same here    wut?     Same here, just
     with \S+, so we can                   repeat         use \S+
       drop it                              dots?

所以我们可以通过使用来简化它\S+@\S+\.\S+,但是等等?如果是这样,我们可以只使用\S+它是无意义的。让我们使用^[^\s@]+@[^\s@]+$.

  • ^: 行首
  • [^\s@]+: 匹配除空格和@
  • @: 匹配@
  • [^\s@]+: 匹配除空格和@
  • $: 行结束

修复你的正则表达式

让我们修复您的正则表达式。请注意,在字符类中,您不需要转义点、下划线等...将连字符放在开头,您也不需要转义它。在此之后,让我们删除那个丑陋的量词\.+,结果应该是这样的: ^\S+([-_.]*\S+[-_]?)*@\S+([-_]?\S+)*\.([-_]?\S)+(\.?\S+)*$/

现在通过消除正则表达式的某些部分,我找到了罪魁祸首。这是\S+

^\S+([-_.]*\S+[-_]?)*@\S+([-_]?\S+)*\.([-_]?\S)+(\.?\S+)*$
     here --^

所以你的最终正则表达式应该是^\S+[-_.]*@\S+([-_]?\S+)*\.([-_]?\S)+(\.?\S+)*$.
看到它工作!

现在如果你问我为什么?老实说,我不知道,但我一如既往地建议阅读以下文章:停止使用复杂的正则表达式验证电子邮件地址

于 2013-07-18T10:44:30.280 回答
2

问题肯定出在您的正则表达式中:它在病态上效率低下。基本上,您有多个可以匹配相同字符的连续部分,全部由开放式量词(*+)控制。这创建了正则表达式在放弃匹配之前必须检查的天文数字的“路径”。事实上,这种问题通常只有在无法匹配时才会变得明显,但是您已经设法在应该匹配的正则表达式上触发它。

我怀疑你正在尝试这样的事情:

/^[a-z]+(?:[_.-][a-z]+)*@[a-z]+(?:\.[a-z]+)*$/i

在任何人开始批评之前,我知道[a-z]+不比\S+. 我只是想解释他的正则表达式有什么问题。这个想法是强制用户名和域名以字母开头,同时允许它们围绕分隔符分隔成块,如.,-_. 这就是它如此复杂的原因

这个正则表达式最重要的特点是它总是向前移动。当[a-z]+用完要消耗的字母时,它看到的下一个东西必须是分隔符之一、一个 at 符号 ('@') 或字符串的结尾(取决于它匹配的地址的哪一部分)。如果它没有看到预期的结果,则匹配尝试立即失败。

在您的正则表达式中,该\S+ 部分最初会吞噬整个字符串,然后开始一次后退一个字符,以便为下一部分提供匹配的机会。这个过程对每个\S+. 正如 HamZa 所观察到的,这就是正则表达式引擎花费大部分时间的地方。但\S+杀死你的不是唯一,而是正则表达式的结构。

于 2013-07-18T12:22:28.530 回答