C# 为什么用Regex.IsMatch检查这个字符串会导致CPU达到100%?

C# 为什么用Regex.IsMatch检查这个字符串会导致CPU达到100%?,c#,.net,regex,C#,.net,Regex,在特定字符串上使用Regex.IsMatch(C#,.Net 4.5)时,CPU达到100% 字符串: https://www.facebook.com/CashKingPirates/photos/a.197028616990372.62904.196982426994991/1186500984709792/?type=1&permPage=1 模式: ^http(s)?://([\w-]+.)+[\w-]+(/[\w- ./?%&=])?$ 完整代码: Regex.Is

在特定字符串上使用
Regex.IsMatch
(C#,.Net 4.5)时,CPU达到100%

字符串:

https://www.facebook.com/CashKingPirates/photos/a.197028616990372.62904.196982426994991/1186500984709792/?type=1&permPage=1
模式:

^http(s)?://([\w-]+.)+[\w-]+(/[\w- ./?%&=])?$
完整代码:

Regex.IsMatch("https://www.facebook.com/CashKingPirates/photos/a.197028616990372.62904.196982426994991/1186500984709792/?type=1&permPage=1",
                @"^http(s)?://([\w-]+.)+[\w-]+(/[\w- ./?%&=])?$");
我发现编校URL可以防止这个问题。修订的URL:

https://www.facebook.com/CashKingPirates/photos/a.197028616990372.62904.196982426994991/1186500984709792

但是仍然非常有兴趣了解这是什么原因。

正如nu11p01n73R指出的,正则表达式有很多回溯。这是因为表达式的各个部分都可以匹配相同的内容,这使引擎在找到结果之前有很多选择

可以通过更改正则表达式使各个部分更具体来避免这种情况。在您的情况下,原因是您希望匹配一个实点,但使用了match all字符
。您应该将其转义到
\。

这应该已经大大减少了回溯需求,并使其变得更快:

^http(s)?:/([\w-]+\)+[\w-]+(/[\w-./?%&=])$
如果要实际匹配原始字符串,则需要在末尾向字符类添加一个量词:

^http(s)?:/([\w-]+\)+[\w-]+(/[\w-./?%&=]+)$
↑
我建议您查看网站,测试正则表达式

正则表达式的更正版本如下:

^(https?://(?:[\w]+\.?[\w]+)+[\w]/?)([\w\./]+)(\?[\w-=&%]+)?$
它还有3个组:

  • group1=主url(例如:facebook.com)
  • group2=子URL(例如:/CashKingPirates/photos/a.197028616990372.62904.1969824269949991/118650098709792/
  • group3=变量(例如:?type=1&permPage=1)

  • 还要记住,在检查正则表达式中点(.)的实际字符时,必须使用\。not。

    您的正则表达式会遭受灾难性的回溯。。您只需使用

    ^http(s)?://([\w.-])+(/[\w ./?%&=-]+)*$
    
    见演示


    正则表达式匹配涉及大量回溯。有关详细信息,请阅读,因为您没有在点之前加反斜杠,可能您的正则表达式是非常复杂的
    ^http(s)?://.+$
    (即匹配http://或https://后跟任何内容).你为什么不使用URI类?@SalmanA在看到潜在的危害后,我实际上从regex改为URI.TryCreate。我不能告诉你他问题的确切原因,但据我所知[\w-]+在他的正则表达式中完全没有必要。regxer专门为js设计,它不支持lookbehinds。谢谢,但您建议的正则表达式与原始字符串不匹配。虽然它很快。事实上,这是导致灾难性回溯的唯一确切原因:点没有转义,没有被视为文字字符er和可以匹配任何东西。@Nir:注意,这正好回答了您的问题。您现在可以很容易地纠正您的模式。这是一个糟糕的解决方案,降低了原始正则表达式的意图。