2010-07-17 108 views
1

這段代碼有一個錯誤,我找不到它。我需要什麼缺失的角色?正則表達式錯誤php

preg_replace(/<(?!\/?(?:'.implode('|',$white).'))[^\s>]+(?:\s(?:(["''])(?:\\\1|[^\1])*?\1|[^>])*)?>/','',$html); 
+0

你有什麼錯誤,什麼是不正確的結果,最重要的是你想達到什麼? – HoLyVieR 2010-07-17 20:50:46

+5

他正試圖解析HTML使用PHP!抓住他! – 2010-07-17 21:21:46

+0

正如下面的Aircule所提到的,我建議你考慮不使用正則表達式來解析HTML。這只是要求麻煩和痛苦。 – 2010-07-18 00:48:49

回答

4

它看起來像在其他的東西,你就錯過了一個單引號:

preg_replace('/<(?!\/?(?:' . implode('|',$white) . '))[... 
      ^
      here! 

此外,由於模式包含單引號,這些也必須由前導反斜槓進行轉義。

或者,您也可以使用heredoc syntax;這將不需要在模式中引用任何轉義,並且表達式可以嵌入到擴展中。

$pattern = <<<EOD 
/pattern{embeddedExpression}morePattern/ 
EOD; 

... preg_replace($pattern, ...) 
0

那麼,這部分是錯誤的:

(["'])(?:\\\1|[^\1])*?\1 

這應該匹配包圍在單或雙引號,可能包括反斜槓轉義引號的序列。但它不起作用,因爲反向引用在字符類中不起作用。 \1以八進制表示法處理爲數字1,因此[^\1]與除U+0001以外的任何字符匹配。

如果它似乎大部分時間工作,這是因爲不情願的量詞(*?)。 (?:\\\1|[^\1])*?中的第一個替代方法正確地使用了一個轉義引用,但否則它只是不情願地匹配任何字符,直到它看到一個未轉義的引用。它在格式正確的文本上可以正常工作,但可以在額外的報價中折騰並且無法使用。

匹配「除了捕獲的組#1以外的任何內容」的正確方法是(?:(?!\1).)* - 即一次只消費一個字符,但僅在該預見確認它不是捕獲的文本的第一個字符之後。但我認爲你會更好地分開處理每種報價。這個正則表達式很複雜。

'~<(?!/?+(?:'.implode('|',$white).')\b)[^\s>]++(?:\s++'. 
'(?:[^\'">]++|"(?:[^"\\]++|\\")*+"|\'(?:[^\'\\]++|\\\')*+\')*+)?+>~' 

通知白名單中交替後加入\b(字邊界)的。否則,如果您的列表中包含(例如)<B>,則會無意中將<BODY><BLOCKQUOTE>標籤列入白名單。

我也用佔有慾量詞(*+++?+)無處不在,因爲這正則表達式的書寫方式,我知道回溯永遠是有用的。如果它失敗了,我希望它儘快失敗。

現在我已經告訴過你如何讓正則表達式工作了,讓我強烈要求你不要使用它。這項工作太複雜,太重要,不適合像正則表達式這樣不適合的工具。如果你真的從一本關於PHP安全的書中得到了這個正則表達式,我建議你把錢還給你。