正则表达式中的Firefox长度限制(这是一个错误?)

时间:2013-07-18 10:17:01

标签: regex firefox

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

问题是验证在Chrome中运行得很好但在Firefox中失败了,我想知道它是否是一个错误,或者正则表达式是否有错误导致错误。

请查看此小提琴,了解完整的测试用例:http://jsfiddle.net/KQvgJ/

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

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

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

2 个答案:

答案 0 :(得分: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+)*$ See it working !

现在,如果你问我为什么?我老实说不知道,但我一如既往地推荐阅读以下文章:Stop Validating Email Addresses With Complicated Regular Expressions

答案 1 :(得分:2)

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

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

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

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

这个正则表达式最重要的特征是它始终向前发展。当[a-z]+耗尽要使用的字母时,它看到的下一件事必须是分隔字符之一,符号('@')或字符串的结尾(取决于匹配的地址部分)。如果它没有看到它的期望,则匹配尝试立即失败。

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