2012-07-06 30 views
3

我有一個相當基本的情況,我有一個字符串數組,我想在一個字符串中找到所有匹配的字符串,並在它們周圍放上強大的標籤。這是我到目前爲止有:PHP preg_replace函數替換以前的匹配

$searchWords = array("test","this","s"); 

for($i=0;$i<sizeof($searchWords);$i++) { 
    $searchWords[$i] = "/".preg_quote($searchWords[$i])."/i"; 
} 

$label = "This is a test string."; 

$result = preg_replace($searchWords, "<strong>$0</strong>", $label); 

echo($result); 

的問題是,preg_replace函數的功能似乎是匹配的「S」,因爲它們可以代替搜索字詞對抗強者的標籤。所以我結束了:

<強> Thisstrong >是<強> teststrong >。

當我真正想要的是:

<強>這< /強>我<強>小號< /強>一個<強>測試< /強>。

那麼,你們可以建議我哪裏去錯了嗎?

任何幫助非常感謝,我正在撕掉我的頭髮,我必須接近。

回答

3

你不想做三所替代,但一:

$result = preg_replace("#" . implode($searchWords, "|") . "#", "<strong>$0</strong>", $label); 

hakre的編輯:這類似於這樣或那樣的,或者字符串。第一場比賽將會進行。因此,從最長的字符串開始,將最小的字符串作爲最後一個字符串。

二進制對這個編輯答案:看評論


完整版:

<?php 
$searchWords = array("t", "test", "this"); 
usort($searchWords, function ($a, $b) { return strlen($b) - strlen($a); }); 

foreach ($searchWords as &$word) 
{ 
    $word = preg_quote($word); 
} 
unset($word); 

$label = "This is a test string."; 

$searchWords = implode($searchWords, "|"); 
$result = preg_replace("#{$searchWords}#i", "<strong>$0</strong>", $label); 

echo($result); 
+0

@hakre,是不是默認使用最大字符串可能嗎?是不是正則表達式如何運作,除非你使用「不真實」的標誌? – binaryLV 2012-07-06 12:30:47

+0

貪心只是爲了重複,這裏沒有重複。你可以把'array_map'看作'preg_quote'。 – hakre 2012-07-06 12:33:14

+0

@hakre,所以'preg_replace(「#s | tests#i」,「some tests」,'* $ 0 *')''必須返回'* s * ome te * s * t * s *',對嗎?因爲pattern中的第一個字符串是's',而不是'tests'。儘管如此,它在5.3.14上返回'* s * ome * tests *'。如果我在模式中切換's'和'tests',它的確如此。 – binaryLV 2012-07-06 12:37:22

0

確保這種情況不會發生的最簡單方法是使用兩個不會冒險被替換的特殊「faketags」,然後替換它們,或者指定單詞必須是完整的單詞匹配並開始和結束在一個字邊界。

$result = preg_replace($searchWords, "<_^_>$0</_^_>", $label); 
    $result = str_replace('_^_', 'strong', $result); 

$searchWords[$i] = '/\b'.preg_quote($searchWords[$i]).'\b/i'; 

第二個是更優雅(快 - 還加快了搜索,我敢打賭),但會阻止您使用部分文字替換。