Замена смайликов - PHP - PullRequest
       2

Замена смайликов - PHP

5 голосов
/ 12 января 2012

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

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!

Ответы [ 3 ]

5 голосов
/ 12 января 2012

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

$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", "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]);

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

0 голосов
/ 12 января 2012

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

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 голосов
/ 12 января 2012

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

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

тогда это просто заглянуть в preg_replace ($ smiles, $ t_smiles, $ text)

...