2012-01-12 103 views
5

我需要將文字表情符號替換爲html圖像標籤。我整理了以下數據:表情符號替換 - PHP

private $smile = array(">:]", ":-)", ":)", ":o)", ":]", ":3", ":c)", ":>", "=]", "8)", "=)", ":}", ":^)"); 
private $laugh = array(">:D", ":-D", ":D", "8-D", "x-D", "X-D", "=-D", "=D", "=-3", "8-)"); 
private $sad = array(">:[", ":-(", ":(", ":-c", ":c", ":-<", ":-[", ":[", ":{", ">.>", "<.<", ">.<"); 
private $wink = array(">;]", ";-)", ";)", "*-)", "*)", ";-]", ";]", ";D", ";^)"); 
private $tongue = array(">:P", ":-P", ":P", "X-P", "x-p", ":-p", ":p", "=p", ":-Þ", ":Þ", ":-b", ":b", "=p", "=P"); 
private $surprise = array(">:o", ">:O", ":-O", ":O", "°o°", "°O°", ":O", "o_O", "o.O", "8-0"); 
private $annoyed = array(">:\\", ">:/", ":-/", ":-.", ":\\", "=/", "=\\", ":S"); 
private $cry = array(":'(", ";'("); 

private $t_smile = "<img class=\"smiley\" src=\"/images/emoticons/smile.png\"/>"; 
private $t_laugh = "<img class=\"smiley\" src=\"/images/emoticons/laugh.png\"/>"; 
private $t_sad = "<img class=\"smiley\" src=\"/images/emoticons/sad.png\"/>"; 
private $t_wink = "<img class=\"smiley\" src=\"/images/emoticons/wink.png\"/>"; 
private $t_tongue = "<img class=\"smiley\" src=\"/images/emoticons/tongue.png\"/>"; 
private $t_surprise = "<img class=\"smiley\" src=\"/images/emoticons/surprise.png\"/>"; 
private $t_annoyed = "<img class=\"smiley\" src=\"/images/emoticons/annoyed.png\"/>"; 
private $t_cry = "<img class=\"smiley\" src=\"/images/emoticons/cry.png\"/>" 

我目前只是做例如:

$str = str_replace($this->laugh, $this->t_laugh, $str); 

每個組。它工作正常,但我需要更換隻發生在字不包圍字母或其他數字。換句話說,我需要編譯一個包含每個表情符號數組的正則表達式,以便我可以使用preg_replace而不是str_replace。有沒有一種方法可以輕鬆做到這一點,而不是硬編碼正則表達式並轉義所有必要的字符?

編輯:

另外,我需要匹配和替換它出現在一個字符串的開頭和結尾的表情,所以用空間技術的簡單填充是不夠的。

編輯2:

我跟着馬克的例子和預編譯使用preg_quote從陣列中的正則表達式:

private $smile = "#(^|\W)(\>\:\]|\:-\)|\:\)|\:o\)|\:\]|\:3|\:c\)|\:\>|\=\]|8\)|\=\)|\:\}|\:\^\))($|\W)#"; 
private $laugh = "#(^|\W)(\>\:D|\:-D|\:D|8-D|x-D|X-D|\=-D|\=D|\=-3|8-\)|xD|XD|8D|\=3)($|\W)#"; 
private $sad = "#(^|\W)(\>\:\[|\:-\(|\:\(|\:-c|\:c|\:-\<|\:-\[|\:\[|\:\{|\>\.\>|\<\.\<|\>\.\<)($|\W)#"; 
private $wink = "#(^|\W)(\>;\]|;-\)|;\)|\*-\)|\*\)|;-\]|;\]|;D|;\^\))($|\W)#"; 
private $tongue = "#(^|\W)(\>\:P|\:-P|\:P|X-P|x-p|\:-p|\:p|\=p|\:-Þ|\:Þ|\:-b|\:b|\=p|\=P|xp|XP|xP|Xp)($|\W)#"; 
private $surprise = "#(^|\W)(\>\:o|\>\:O|\:-O|\:O|°o°|°O°|\:O|o_O|o\.O|8-0)($|\W)#"; 
private $annoyed = "#(^|\W)(\>\:\\|\>\:/|\:-/|\:-\.|\:\\|\=/|\=\\|\:S|\:\/)($|\W)#"; 
private $cry = "#(^|\W)(\:'\(|;'\()($|\W)#"; 

用了preg_replace完美的作品!

+4

您應該爲此使用關聯數組。 – 2012-01-12 03:47:19

+0

你可以在數組中的任何一邊添加一個空格並繼續使用str_replace嗎? – Frank 2012-01-12 03:48:17

回答

5

$pat = '#(^|\W)'.preg_quote($this->laugh,'#').'($|\W)#'; 
$str = str_replace($pat, $this->t_laugh, $str); 

這基本上意味着圖釋可以位於字符串的開頭或由非單詞字符繼續,並且必須緊跟在字符串的末尾或另一個非單詞字符之後。如果您的圖釋包含任何特殊的正則表達式字符,則需要preg_quote

此外,更好的格式可能是:

$emoticons = array(
    'smile' => array('<img src...', array('>:]',':-)',...), 
    'laugh' => array('<img src....', array(...)), 
    ... 
) 

然後你可以遍歷一切。


更新

應該使用負lookarounds,而不是匹配並排側表情。然後它不會嘗試匹配周圍的空間。

<?php 
$smile = array(">:]", ":-)", ":)", ":o)", ":]", ":3", ":c)", ":>", "=]", "8)", "=)", ":}", ":^)"); 
$laugh = array(">:D", ":-D", ":D", "8-D", "x-D", "X-D", "=-D", "=D", "=-3", "8-)"); 
$sad = array(">:[", ":-(", ":(", ":-c", ":c", ":-<", ":-[", ":[", ":{", ">.>", "<.<", ">.<"); 
$wink = array(">;]", ";-)", ";)", "*-)", "*)", ";-]", ";]", ";D", ";^)"); 
$tongue = array(">:P", ":-P", ":P", "X-P", "x-p", ":-p", ":p", "=p", ":-Ã", ":Ã", ":-b", ":b", "=p", "=P"); 
$surprise = array(">:o", ">:O", ":-O", ":O", "°o°", "°O°", ":O", "o_O", "o.O", "8-0"); 
$annoyed = array(">:\\", ">:/", ":-/", ":-.", ":\\", "=/", "=\\", ":S"); 
$cry = array(":'(", ";'("); 

$ary = array_merge($smile, $laugh, $sad, $wink, $tongue,$surprise,$annoyed,$cry); 

foreach ($ary as $a) 
{ 
     $quoted[] = preg_quote($a, '#'); 
} 

$regex = implode('|', $quoted); 


$full = '#(?!<\w)(' . $regex .')(?!\w)#'; 
echo $full.PHP_EOL; 
$str = "Testing :) emoticons :D :("; 

preg_match_all($full, $str, $matches); 
print_r($matches[0]); 

此外,嘗試寫正則表達式的模式時使用單引號,因爲雙引號允許轉義序列,而單引號不會解釋轉義序列。即使用雙引號時,您有時需要加倍你的斜線。

+0

'preg_quote'接受一個數組嗎?如果沒有,編寫一個循環遍歷數組的方法,並返回帶有周圍模式的轉義數組。 – Josh 2012-01-12 03:57:25

+1

@Josh:不,它不。 http://ca.php.net/manual/en/function.preg-quote.php。你也可以把所有的「笑容」放進一個單一的正則表達式中,通過用一個管道(在他們被預先引用之後)將它們加以內化。最終的字符串應該如下所示:'#(^ | \ W)(:\ \)|:\)|>:\])($ | \ W)#' – mpen 2012-01-12 04:00:41

+0

確實如此,它只會邏輯或通過每個模式。好的解決方案我會將其添加到您的答案中。 – Josh 2012-01-12 04:05:19

0

也許有一個格式化圈像

for($i=0;$i<count($smiles);++$i){ 
    $smiles[$i]="~\s".$smiles[$i]."\s~"; 
} 

那麼如果你想使用正則表達式,它只是一個下跌中的preg_replace($微笑,$ t_smiles,$文本)

0

這些方針的東西可能是你在找什麼:

function toRegex(array $emotes) { 
    foreach ($emotes as &$emote) 
     $emote = preg_quote($emote, "/"); 
    return "/\b" . implode($emotes, "\b|\b") . "\b/"; 
} 

$imaged = preg_replace(toRegex($smiles), $t_smiles); 

此外,正如馬克所提到的,你會更好地與所有的表情符號的巨型陣列比你有一百個變量不大手動處理。

+0

字邊界在這裏不起作用我相信一定要有一個單詞字符和一個非單詞字符表情符號中的':'和')不是單詞字符,所以'\ b'不能匹配字符串中的任何內容,比如'「:)」'(例如任何一邊的空格)。實際上,它會*匹配'x:)',這與我們想要的完全相反。 – mpen 2012-01-13 01:55:26