1

当我没有在“这里”一词之前插入任何不在[,.]中的符号时,此正则表达式查询运行良好:

RegEx.Replace("My products or something / else here ", "My ((?:[a-z']* ??)*?)\s*([,.]|$| here)", "")

但是如果我在“这里”之前插入一个不在[,.]中的符号,它会非常非常慢(冻结大约 3-5 秒或更长时间) 。例如,我在“这里”一词之前插入符号“/”:

RegEx.Replace("My products or something / else here ", "My ((?:[a-z']* ??)*?)\s*([,.]|$| here)", "")

当我将 / 添加到我的模式[,.]时,问题就消失了:

RegEx.Replace("My products or something / else here ", "My ((?:[a-z']* ??)*?)\s*([/,.]|$| here)", "")

但我希望我的正则表达式忽略符号 / 而不是匹配符号 / 作为我句子的结尾。为什么会出现这个问题以及如何解决?

4

1 回答 1

4

你是灾难性回溯的受害者。这部分:

(?:[a-z']* ??)*?

可以以指数数量的可能组合匹配单词。由于空格是可选的,因此else可以在所有这些变体中单独匹配单词(其中括号表示与内部组的一个“实例”匹配的内容):

(else)
(els)(e)
(el)(se)
(el)(s)(e)
(e)(lse)
(e)(l)(se)
(e)(ls)(e)
(e)(l)(s)(e)

对于更长的单词,尤其是整个句子,这会爆炸。通常,只要您有嵌套重复,就会出现问题,并且不清楚一个重复在哪里结束,另一个在哪里开始。然后,如果没有匹配,引擎需要回溯所有这些情况,然后才能声明失败。如果有匹配,回溯通常是不必要的,并且问题不会被注意到。最好的解决方法是使用“unrolling-the-loop”模式,使重复中的空间是强制性的:

"My ([a-z']*(?: [a-z']*)*?)\s*([,.]|$| here)"

现在空格是强制性的,重复的每个“实例”都必须匹配整个单词,这应该可以解决问题。

于 2013-09-22T06:35:56.943 回答