悬挂高正常CPU的.NET正则表达式

时间:2014-10-03 20:22:37

标签: .net regex

这是一个奇怪的.NET正则表达式问题,我无法弄清楚。我试图在我的论坛应用中解析一些HTML。我还没有改变代码,但在某些环境中,正则表达式根本就不会返回。我可以在应用程序中重现它:

第66行:https://github.com/POPWorldMedia/POPForums/blob/master/PopForums/Services/TextParsingService.cs

text = Regex.Replace(text, @"(<iframe )(\S+ )*(src=""http://www.youtube.com/embed/)(\S+)("")( *\S+)*( */iframe>)", "http://www.youtube.com/watch?v=$4", RegexOptions.IgnoreCase);

它窒息的输入字符串是:

<p>This is an <strong>important</strong> <em>preview</em> of a post.</p>[quote]<p>This is a quote.<br /></p>[/quote]<p><iframe width="640" height="360" src="http://www.youtube.com/embed/Zey3WWThErw" frameborder="0" allowfullscreen></iframe></p><p>O look! YouTube!</p>

最终会在这里超时: http://regexlib.com/RETester.aspx

主机进程,在这种情况下,IIS在本地大约50%(一个核心,我假设),永远不会放弃或返回。我完全难过了。我在Azure上的一个网站上运行相同的代码并且它并没有在那里窒息。

2 个答案:

答案 0 :(得分:3)

(\S+ )*( *\S+)*部分导致批次回溯。

考虑简单地用.*替换它们。它不是100%相当,但我认为它应该与我想要做的事情一起工作。

text = Regex.Replace(text, @"(<iframe )(.)*(src=""http://www.youtube.com/embed/)(\S+)("")(.)*( */iframe>)", "http://www.youtube.com/watch?v=$4", RegexOptions.IgnoreCase);

你的正则表达式会有其他问题,因为它贪婪地发挥作用。如果您的文字中有多个iframe标记,则可能需要尝试此操作以确保没有任何问题。

text = Regex.Replace(text, @"(<iframe )(.)*?(src=""http://www.youtube.com/embed/)(\S+)("")(.)*?( */iframe>)", "http://www.youtube.com/watch?v=$4", RegexOptions.IgnoreCase);

与往常一样,您还应考虑使用HTML解析器而不是正则表达式来执行此类任务。

答案 1 :(得分:1)

唯一的问题是( \ * \S+ )*

发动机特别恼火混合(零/多*与许多+* inside a zero/many group。 在这种情况下,将许多人单一化,问题就解决了。即:( _* _+)*至=&gt; ( _* _)*
这些是导致问题的唯一地方 ,尤其是当许多人可以匹配很多时 不同的人物。

总是先检查一下,不要对回溯感到偏执。

 # @"(<iframe\ )(\S+\ )*(src=""http://www\.youtube\.com/embed/)(\S+)("")(\ *\S)*(\ */iframe>)"

 ( <iframe\  )                            # (1)
 ( \S+ \  )*                              # (2)
 (                                        # (3 start)
      src="http://www \. youtube \. com/embed/ 
 )                                        # (3 end)
 ( \S+ )                                  # (4)
 ( " )                                    # (5)
 ( \ * \S )*                              # (6)
 ( \ */iframe> )                          # (7)

输出:

 **  Grp 0 -  ( pos 119 , len 121 ) 
<iframe width="640" height="360" src="http://www.youtube.com/embed/Zey3WWThErw" frameborder="0" allowfullscreen></iframe>  
 **  Grp 1 -  ( pos 119 , len 8 ) 
<iframe   
 **  Grp 2 -  ( pos 139 , len 13 ) 
height="360"   
 **  Grp 3 -  ( pos 152 , len 34 ) 
src="http://www.youtube.com/embed/  
 **  Grp 4 -  ( pos 186 , len 11 ) 
Zey3WWThErw  
 **  Grp 5 -  ( pos 197 , len 1 ) 
"  
 **  Grp 6 -  ( pos 231 , len 1 ) 
<  
 **  Grp 7 -  ( pos 232 , len 8 ) 
/iframe>