2014-10-03 44 views
1

這是一個奇怪的.NET正則表達式問題,我找不出來。我試圖解開我的論壇應用程序中的一些HTML。我沒有改變代碼,但在某些環境中,正則表達式根本不會返回。我可以重現它在應用程序:掛用高CPU的.NET正則表達式

線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中的其中一個網站上運行着相同的代碼,它不會在那裏窒息。

+3

強制性:http://stackoverflow.com/a/1732454/3312 – 2014-10-03 20:25:11

+1

是啊,我看到過,我傾向於拒絕它。這是一種已知和可預測的模式。 – 2014-10-03 20:40:32

回答

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解析器,而不是正則表達式來處理這類任務。

+0

是的,那是它!我知道這是一個貪婪的問題,但不知道我是否做得對。非常感謝你! – 2014-10-03 20:45:39

+0

你爲什麼使用'(。)*'和'(。)*?'?如果你想捕獲這些位,量詞應該在組內:'(。*)'和'(。*?)'。但我認爲你根本不需要這些團體。 – 2014-10-04 08:06:03

+0

我盲目地用'.'替換了捕獲組的內容,我的不好。但事實上,他們可能根本不需要。 – Vache 2014-10-04 13:17:21

1

你唯一的問題就是這個(\ * \S+)*

發動機變得特別惱人的混合(零/很多*與許多+* inside a zero/many group
在這種情況下單數化並解決問題。即:(_* _+)*到=>(_* _)*
這些是它引起的問題唯一的地方,尤其是當許多可以匹配很多不同的字符

總是先看看先檢查一下,不要因爲回溯而出現偏執。

# @"(<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>