2011-05-02 85 views
4

要匹配包含某個單詞的字符串,我可以使用pattern「/.*word.*/」。但是,如何匹配一個不包含這個單詞的字符串呢?如何匹配不包含單詞的字符串?

例子:

我需要找到一個大的文本,這是由兩個標籤包圍的子串,並,並具有一定的字符串,如「你好」裏。最好的我想出了:

"@<div>(.*?Hello.?*)</div>@i" 

但它也將匹配序列:

<div>Bye.</div><div>Hello!</div> 

而且我不希望匹配第一對div標籤 - 因此,我要替換」。 *?」像「匹配任何字符串,除了不包含」之類的東西。

測試用例

對於輸入字符串:

<div>Bye.</div><div>Hello!</div> 

我需要趕上

<div>Hello!</div> 
+1

[正則表達式匹配字符串不包含單詞?]的可能重複(http://stackoverflow.com/questions/406230/regular-expression-to-match-string-not-containing-a-word) – Dogbert 2011-05-02 15:18:49

+0

@Dogbert - 這個問題很接近,但是我怎麼能在子模式上使用這個東西呢? – Rogach 2011-05-02 15:28:24

+0

你想要完全匹配什麼?你能寫一個測試用例嗎?你說你看不到第一對div標籤。但是第一對是不包含Hello的那一對,這就是你在表達中所擁有的。那麼你怎麼說你不想匹配那些不包括你想排除的東西的東西呢? – 2011-05-02 15:29:20

回答

4

的問題,更好的標題可能是:「匹配含有特定的子字符串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解析器。

0

你就不能檢查,如果你沒有得到比賽?

如果你正在尋找什麼,但這個詞「詞」:

if(!preg_match("/word/i", $myString)) 

這將運行代碼只有「字」是沒有發現if下方。

+1

不,我不能。實際上,我需要從子模式中檢查它。 – Rogach 2011-05-02 15:19:13

+0

什麼子模式...?你指的是什麼?請更具描述性。 – qJake 2011-05-02 15:20:24

+0

我添加了一個問題的例子。 – Rogach 2011-05-02 15:23:54

3
'~<div>(?!.*?Bye\..*?</div>).+?</div>~' 
+1

@Rogach這是PHP用戶反覆提出的問題,我想知道爲什麼。我還想知道爲什麼答案沒有廣爲人知。謝謝 – eyquem 2011-05-02 16:37:12

相關問題