2013-07-08 77 views
2
$string='print the imprint with the imprinted printing paper'; 

$pattern=array('/print/','/imprint/','/paper/',); 
$replacement=array('imprint','print','machine'); 

輸出:需要自定義同義詞替換文本中的單詞

print the imprint with the imprinted printing machine 

我想我理解正確的話,前兩個圖案被覆蓋對方。我正在考慮讓這變得更加複雜,但REGEX對我來說仍然是巫術。顯示輸入字符串後,我想回到此處:imprint the print with the printed imprinting machine。如果我還可以看到如何使其輸出imprint the print with the imprinted printing machine,那也會很棒。

如果你能解釋你的正則表達式,那會更有幫助。也許以後我可以自己做更多事情。

回答

4

做到這一切置換在一個單一的正則表達式,你會感覺良好,因爲在一個通正則表達式將持續一個更換後,不再試圖再次對陣更換:

$string = 'print the imprint with the imprinted printing paper'; 

// A single array of find => replace 
$replacements = array( 
    'print' => 'imprint', 
    'imprint' => 'print', 
    'paper' => 'machine' 
); 

// Dynamically form the regex, properly escaping it 
$delimiter = '/'; 
$words = array_keys($replacements); 
$regex = $delimiter . '\b(' . implode('|', array_map('preg_quote', $words, array_fill(0, count($words), $delimiter))) . ')\b' . $delimiter; 

正則表達式而形成這個樣子的:

/\b(print|imprint|paper)\b/ 

其中:

  1. \b是AW ord邊界。
  2. ()是一個捕獲組。
  3. print|imprint|paper是這些字的或匹配的一個

最後,做更換:

$result = preg_replace_callback($regex, function($match) use($replacements) { 
    return $replacements[$match[1]]; 
}, $string); 
echo $result; 

will output

imprint the print with the printed imprinting machine 
+0

我想這是我會用,用動態的$替換陣列去用它。一旦我做了更多的測試,我可能會接受這個答案。 – TecBrat

+0

我在[在線測試平臺](http://writecodeonline.com/php/)上試過這個代碼,它工作起來非常棒!我想我可能正在運行PHP 5.2,而匿名函數不起作用。我試過這個解決方法:'function for_callback($ match){0} {0} {0} {0}全局$替換; return $ replacements [$ match [1]]; } $ result = preg_replace_callback($ regex,'for_callback',$ string); echo $ result;'但事情不對。你有什麼想法? – TecBrat

+0

@TecBrat - 我做了您的更改,刪除匿名功能,[它適用於我](http://viper-7.com/LwELBW) – nickb

2

如果您需要做簡單的字符串替換不重複結果字符串多次,您應該使用strtr(),而不是:

strtr($string, array(
    'imprint' => 'print', 
    'print' => 'imprint', 
    'paper' => 'machine', 
)); 

要替換的單詞按字符串長度排序,最具體的第一個。

注意:這當然不像正則表達式那麼靈活,特別是在只替換全部單詞的情況下,即/\bword\b/僅當它自身站立時才與word匹配;這不是你可以用strtr()和朋友做的事情。

使用正則表達式

爲了使preg_replace()在串僅執行單傳,你需要在你更換鍵一起組合成一個單一的表達,即

/imprint|print|paper/ 

該表達式使用交替,由搜索字符串之間的管道字符實現。要僅匹配整個單詞,您需要添加邊界匹配,這是一個特殊的\b序列,用於匹配單詞和非單詞之間的過渡。

/\b(?:imprint|print|paper)\b/ 

這將匹配"imprint"但不"pimprint"

如果你要走這條路線,執行替換需要使用preg_replace_callback();對於每個匹配,它會發現一個自定義函數被執行,您可以在其中確定要替換它的內容。您需要爲它創建一個替換地圖,就像我之前用於示例strtr()的地圖一樣。

$map = array(
    'imprint' => 'print', 
    'print' => 'imprint', 
    'paper' => 'machine', 
); 

$replacer = function($match) use ($map) { 
    // $match[0] holds the found word 
    return $map[$match[0]]; 
}; 

preg_replace_callback('/\b(?:imprint|print|paper)\b/', $string, $replacer); 

使其成爲動態

我創建的手正則表達式,但要使這種靈活的,你需要動態生成此,根據關更換地圖。爲此,我們需要:

  1. 從替換映射中提取鍵;
  2. 轉義任何特殊字符;
  3. 構建最終表達式。

這是你將如何構建表達式:

// step 1 
$replacement_keys = array_keys($map); 
// step 2 
$escaped_keys = array_map(function($key) { 
    return preg_quote($key, '/'); 
}, $replacement_keys); 
// step 3 
$pattern = '/\b(?:' . join('|', $escaped_keys) . ')\b/';