Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript RegExp和字符串组合_Javascript_Regex_Google Chrome - Fatal编程技术网

Javascript RegExp和字符串组合

Javascript RegExp和字符串组合,javascript,regex,google-chrome,Javascript,Regex,Google Chrome,我使用以下RegExp验证电子邮件地址: ^[A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$ 在一封基本的电子邮件上运行它效果很好: /^[A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$/.test('dave@the-tay

我使用以下RegExp验证电子邮件地址:

^[A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$
在一封基本的电子邮件上运行它效果很好:

/^[A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$/.test('dave@the-taylors.org');
但在长字符串上运行它会使Chrome崩溃:

/^[A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$/.test('dddddddddddddddddddddddddddddddddddddddd');
我注意到它大约有40个字符


这个RegExp如此密集的原因是什么?

我认为它与您的regex有关,而不是字符串的长度。我使用下面的正则表达式进行电子邮件验证,它在Chrome上没有崩溃

/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test('dddddddddddddddddddddddddddddddddddddddd');
/([^()[\]\\,;:\s@\“]+(\.[^()[\]\,;:\s@\“]+)*(\“+\”)(\[[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[1,3}.[0-9]{1,3}.]124;([a-zA-Z-0-9]+-dd dd dd dd dd dd dd dd;

不使用正则表达式验证电子邮件。我认为这是大约二十年来的常识。这太复杂了。这里有一个大部分完全验证的例子,甚至没有完全实现标准。编写一个同样的函数要简单得多。当您可以单独验证电子邮件的部分内容时,它就变得微不足道了。此外,与您的情况一样,函数可以更快地完成此操作。

好的,让我们看看这里发生了什么。谢天谢地,您已经将问题简化为应用正则表达式时会发生什么

(d+)*@
不折不扣

ddddd
由于缺少
@
,因此显然无法匹配。但是是什么让正则表达式引擎无法快速解决这个问题呢

实际上,
(d+)*
可以通过以下匹配来实现(每组用空格分隔):

因此,有一种方法可以匹配字符串,而不必拆分字符串,四种方法可以将其拆分为两个字符串,六种方法可以将其拆分为三个字符串,四种方法可以将其拆分为四个字符串,还有一种方法可以将其拆分为五个字符串。所有这些组合都必须由正则表达式引擎进行检查,然后才能在最终必须面对以下
@
时声明匹配失败

为什么它不早点发现呢?一些正则表达式引擎可能可以通过这样一个简化的例子来实现。我敢打赌拉里·沃尔已经把它盖上了。但是你的实际正则表达式要复杂一点,所以我想这将很难事先弄清楚。另外,有一个简单的方法可以确保所有这些组合不会发生。但我稍后会再谈这个问题

我一直在想,一个较长的字符串会有多少这样的组合,而不是那些微不足道的五个
d
s:

让我们取一个长度为
m
的字符串(可以在
m-1
的不同位置进行分割)。比如说
n=m-1
。然后,您可以按如下方式计算组合数:

1 + (n!/(1! * (n-1)!)) + (n!/(2! * (n-2)!)) + ... + (n!/(n! * (n-n)!))
第一个和最后一个项目始终为1,但中间的项目可能会变得相当大。让我们编写一个小型Python程序:

>>> from math import factorial as f
>>> def comb(n,x):
...    return f(n) // (f(x) * f(n-x))
...
>>> def ways_to_split(len):
...    return 1 + sum(comb(len-1,x) for x in range(1,len))
...
>>> ways_to_split(5)
16
好的,似乎有用。让我们试试更大的:

>>> ways_to_split(10)
512
>>> ways_to_split(40)
549755813888
>>> ways_to_split(100)
633825300114114700748351602688
嘿,这里有一个模式:
ways\u-to\u-split(n)
等于
2**(n-1)
。看看有没有证据。无论如何您的正则表达式具有
O(2^n)
复杂性。好吧,现在你明白为什么这可能需要一段时间

谢天谢地,许多正则表达式引擎提供了针对这种情况的保护:所有格量词或原子捕获组

(d++)*

两者都确保无论
d+
匹配了什么,都不会因为尝试其他组合而再次放弃。好消息,对吗

好吧,如果你使用JavaScript就不会了。它不支持这两种功能

因此,您需要重写正则表达式,使其不易受到如下回溯的影响:

而不是

(([_\.\-]?[a-zA-Z0-9]+)*)
使用


或者停止尝试使用正则表达式验证无法可靠工作的电子邮件地址。

问题的根源在于:

如果第一个
[A-Za-z0-9]+
(顺便说一句,您遗漏了
+
)的字母数字字符已用完,而下一个字符不是分隔符(
[.-]
),则匹配尝试应立即失败

正则表达式的情况是,第一个
[A-Za-z0-9]+
开始后退,放弃它刚刚一个接一个匹配的字符,让第二个
[A-Za-z0-9]+
(在
*
循环中)尝试匹配它们。这是它必须尝试的许多组合(正如蒂姆的论文答案所解释的)☺), 这一切都毫无意义

现在看看这个:

^[A-Za-z0-9]+([.-][A-Za-z0-9]+)*@[A-Za-z0-9]+([.-][A-Za-z0-9]+)*\[A-Za-z]{2,}$
此正则表达式不会进入
*
循环,除非它实际看到一个分隔符字符。
*
中的子表达式可能是可选的,但它匹配的任何内容都必须以
\uuu
-
开头。同样,如果正则表达式成功匹配本地部分和下一个字符不是
@
,它会立即退出,而你的会再次陷入回溯

根据RegexBuddy的说法,您的regex需要57个步骤来匹配
dave@the-taylors.org
,我的代码分17步完成。而你的代码锁定在另一个字符串上,我的代码则分5步报告匹配失败

寓意是:永远不要在不可选择的事情上使用
*
量词



免责声明:我不赞成使用此正则表达式或任何其他正则表达式来匹配电子邮件地址。我只是解释问题中的正则表达式有什么问题。

是的,我很好奇正则表达式造成的损害是什么。感谢您发布电子邮件正则表达式,这很有帮助,有趣的是,这在Firefox中很好t也会使Firefox上的IE 9崩溃,即使是长度为4096的“dddddd…”字符串也会崩溃。作为记录,我可以将其归结为
/[a-d]([a-d]+)+a/.test('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
(?>d+)*
(([_\.\-]?[a-zA-Z0-9]+)*)
[a-zA-Z0-9]+([_.-][a-zA-Z0-9]+)*