Замена Emoticon – PHP

Мне нужно заменить текстовые смайлики на html-теги изображений. Я составил следующие данные:

private $smile = array(">:]", ":-)", ":)", ":o)", ":]", ":3", ":c)", ":>", "=]", "8)", "=)", ":}", ":^)"); private $laugh = array(">:D", ":-D", ":D", "8-D", "xD", "XD", "=-D", "=D", "=-3", "8-)"); private $sad = array(">:[", ":-(", ":(", ":-c", ":c", ":-<", ":-[", ":[", ":{", ">.>", "<.<", ">.<"); private $wink = array(">;]", ";-)", ";)", "*-)", "*)", ";-]", ";]", ";D", ";^)"); private $tongue = array(">:P", ":-P", ":P", "XP", "xp", ":-p", ":p", "=p", ":-Þ", ":Þ", ":-b", ":b", "=p", "=P"); private $surprise = array(">:o", ">:O", ":-O", ":O", "°o°", "°O°", ":O", "o_O", "oO", "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. Есть ли способ сделать это легко, а не жестко кодировать регулярное выражение и избежать всех необходимых символов?

РЕДАКТИРОВАТЬ:

Кроме того, мне нужно сопоставить и заменить смайлики, которые появляются в начале и конце строки, поэтому простого заполнения с помощью космической техники недостаточно.

EDIT 2:

Я последовал примеру Марка и предварительно скомпилировал регулярное выражение из массивов, используя preg_quote как:

 private $smile = "#(^|\W)(\>\:\]|\:-\)|\:\)|\:o\)|\:\]|\:3|\:c\)|\:\>|\=\]|8\)|\=\)|\:\}|\:\^\))($|\W)#"; private $laugh = "#(^|\W)(\>\:D|\:-D|\:D|8-D|xD|XD|\=-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|XP|xp|\:-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!

Если вы хотите использовать регулярное выражение:

 $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(...)), ... ) 

Тогда вы можете перебрать все.


Обновить

Вместо этого следует использовать негативные образы, чтобы сопоставлять бок о бок смайлики. Тогда он не будет пытаться сопоставить окружающие пространства.

 <?php $smile = array(">:]", ":-)", ":)", ":o)", ":]", ":3", ":c)", ":>", "=]", "8)", "=)", ":}", ":^)"); $laugh = array(">:D", ":-D", ":D", "8-D", "xD", "XD", "=-D", "=D", "=-3", "8-)"); $sad = array(">:[", ":-(", ":(", ":-c", ":c", ":-<", ":-[", ":[", ":{", ">.>", "<.<", ">.<"); $wink = array(">;]", ";-)", ";)", "*-)", "*)", ";-]", ";]", ";D", ";^)"); $tongue = array(">:P", ":-P", ":P", "XP", "xp", ":-p", ":p", "=p", ":-Ã", ":Ã", ":-b", ":b", "=p", "=P"); $surprise = array(">:o", ">:O", ":-O", ":O", "°o°", "°O°", ":O", "o_O", "oO", "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]); 

Кроме того, попробуйте использовать одиночные кавычки при написании шаблонов регулярных выражений, потому что двойные кавычки позволяют escape-последовательности, а одинарные кавычки не будут интерпретировать escape-последовательность. т. е. вам иногда нужно удвоить свои косые черты при использовании двойных кавычек.

Возможно, есть петля форматирования

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

то это просто переход к preg_replace ($ улыбки, $ t_smiles, $ text)

Что-то в этом направлении, вероятно, то, что вы ищете:

 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); 

Кроме того, как отмечалось выше, вам будет лучше с гигантским массивом всех смайликов, чем сотня небольших переменных, с которыми вам приходится иметь дело вручную.