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

Nir*_*Nir 16 .net c# regex

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

串:

https://www.facebook.com/CashKingPirates/photos/a.197028616990372.62904.196982426994991/1186500984709792/?type=1&permPage=1
Run Code Online (Sandbox Code Playgroud)

图案:

^http(s)?://([\w-]+.)+[\w-]+(/[\w- ./?%&=])?$
Run Code Online (Sandbox Code Playgroud)

完整代码:

Regex.IsMatch("https://www.facebook.com/CashKingPirates/photos/a.197028616990372.62904.196982426994991/1186500984709792/?type=1&permPage=1",
                @"^http(s)?://([\w-]+.)+[\w-]+(/[\w- ./?%&=])?$");
Run Code Online (Sandbox Code Playgroud)

我发现编辑URL可以防止出现此问题.编辑的URL:

https://www.facebook.com/CashKingPirates/photos/a.197028616990372.62904.196982426994991/1186500984709792
Run Code Online (Sandbox Code Playgroud)

但仍然非常有兴趣了解导致这种情况的原因.

pok*_*oke 12

正如nu11p01n73R指出的那样,你的正则表达式有很多回溯.那是因为你的表达式的部分都可以匹配相同的东西,这使得引擎在找到结果之前必须尝试许多选择.

您可以通过更改正则表达式来避免这种情况,从而使各个部分更具体.在你的情况下,原因是你想匹配一个真正的点,但使用匹配所有字符..你应该逃避\..

这应该已经减少了很多回溯需求并使其快速:

^http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=])?$
Run Code Online (Sandbox Code Playgroud)

如果你想真正匹配原始字符串,你需要在最后给字符类添加一个量词:

^http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]+)?$
                                           ?
Run Code Online (Sandbox Code Playgroud)

  • 实际上,这是导致灾难性回溯的唯一且确切的原因:点没有逃脱,不被视为文字角色,可以匹配任何东西.@Nir:请注意,这完全回答了你的问题.您现在可以轻松纠正您的模式. (3认同)

Afs*_*deh 5

我建议你查看http://regexr.com/网站,测试你的正则表达式.

正则表达式的更正版本是这样的:

^(https?://(?:[\w]+\.?[\w]+)+[\w]/?)([\w\./]+)(\?[\w-=&%]+)?$
Run Code Online (Sandbox Code Playgroud)

它还有3组:

  1. group1 =主网址(例如:facebook.com)
  2. group2 =子网址(例如:/CashKingPirates/photos/a.197028616990372.62904.196982426994991/1186500984709792/
  3. group3 =变量(例如:?type = 1&permPage = 1)

还记得要检查正则表达式中点(.)的实际字符,你必须使用\.没有.