的問題,更好的標題可能是:「匹配含有特定的子字符串DIV
元素。」首先必須說的是,正則表達式不是這份工作的最佳工具。使用HTML解析器解析標記會更好,然後在每個DIV
元素的內容中搜索所需的子字符串。這就是說,因爲你不想了解更多關於如何使用正則表達式來匹配那些不是別的東西的東西,所以下面描述了用正則表達式做這件事的有限方式。
由於Dogbert正確指出,這個問題確實是Regular expression to match string not containing a word?的重複。但是,我發現你已經看到了這個問題,但需要知道如何將這種技術應用到子模式。
要匹配不包含特定單詞(或多個單詞)的字符串(子模式)的一部分,您需要在每個字符之前應用負向先行斷言檢查。這裏是你如何處理DIV
標籤之間的文字。請注意,僅使用一個正則表達式時,因爲DIV
元素可能是嵌套的,所以在嵌套的DIV
元素的「最裏面」內找到"HELLO"
是合理的。
僞代碼:
- 比賽開幕
DIV
標籤。
- 懶人匹配零個或多個字符,其中每個字符不是
<div
或</div
的開頭。
- 一旦找到想要的字符串:
"HELLO"
找到,繼續並匹配它。
- 繼續(貪婪地)匹配零個或多個字符,每個字符不是
<div
或</div
的開頭。
- 匹配關閉
</div>
標記。
注意,只匹配「最裏面的」 DIV
內容,有必要排除這兩個<DIV
和</DIV
而在一次掃描元素的內容一個字符。這裏是一個測試的PHP函數的形式對應的正則表達式:
// Find an innermost DIV element containing the string "HELLO".
function p1($text) {
$re = '% # Match innermost DIV element containing "HELLO"
<div[^>]*> # DIV element start tag.
(?: # Group to match contents up to "HELLO".
(?!</?div\b) # Assert this char is not start of DIV tag.
. # Safe to match this non-DIV-tag char.
)*? # Lazily match contents one chara at a time.
\bhello\b # Match target "HELLO" word inside DIV.
(?: # Group to match content following "HELLO".
(?!</?div\b) # Assert this char is not start of DIV tag.
. # Safe to match this non-DIV-tag char.
)* # Greedily match contents one chara at a time.
</div> # DIV element end tag.
%six';
if (preg_match($re, $text, $matches)) {
// Match found.
return $matches[0];
} else {
// No match found
return 'no-match';
}
}
此功能將正確地匹配您的以下測試數據所需的DIV元素:
<div>Bye.</div><div>Hello!</div>
它也將正確查找「HELLO 「嵌套DIV元素的最內層內:
<div>
<div>
Hello world!
</div>
</div>
但是,如前所述,它會不找到‘HELLO’STRI ng位於非最內嵌套的DIV元素內,如下所示:
<div>
Hello,
<div>
world!
</div>
</div>
要做到這一點,這是一個非常複雜的解決方案。
有很多情況下,此解決方案可能會失敗。再來一次。我建議使用HTML解析器。
[正則表達式匹配字符串不包含單詞?]的可能重複(http://stackoverflow.com/questions/406230/regular-expression-to-match-string-not-containing-a-word) – Dogbert 2011-05-02 15:18:49
@Dogbert - 這個問題很接近,但是我怎麼能在子模式上使用這個東西呢? – Rogach 2011-05-02 15:28:24
你想要完全匹配什麼?你能寫一個測試用例嗎?你說你看不到第一對div標籤。但是第一對是不包含Hello的那一對,這就是你在表達中所擁有的。那麼你怎麼說你不想匹配那些不包括你想排除的東西的東西呢? – 2011-05-02 15:29:20