2012-01-12 17 views
5

Ho bisogno di sostituire le emoticon testuali con i tag immagine html. Ho compilato i seguenti dati:Sostituzione emoticon - 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\"/>" 

Attualmente sto semplicemente facendo ad esempio:

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

per ogni gruppo. Funziona bene ma ho bisogno che la sostituzione avvenga solo se le parole non sono circondate da lettere o altre cifre. In altre parole, ho bisogno di compilare una regex che contenga ciascuna matrice di emoticon in modo che io possa usare preg_replace invece di str_replace. C'è un modo per farlo facilmente invece di codificare la regex e sfuggire a tutti i caratteri necessari?

EDIT:

Inoltre, dobbiamo associare e sostituire le emoticon che appaiono all'inizio e alla fine di una stringa, quindi un semplice riempimento con una tecnica spazio non sarà sufficiente.

EDIT 2:

Ho seguito l'esempio di Marco e pre-compilato il regex dagli array utilizzando la funzione preg_quote come:

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

funziona perfettamente con preg_replace!

+4

Si dovrebbe usare un array associativo per questo. –

+0

Puoi semplicemente aggiungere uno spazio su entrambi i lati dei valori nella matrice e continuare a utilizzare str_replace? – Frank

risposta

5

Se si vuole usare una regex:

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

Ciò significa che l'emoticon può trovarsi all'inizio della stringa o proceduto da un carattere diverso da una parola e deve essere seguito dalla fine della stringa o da un altro carattere diverso da una parola. preg_quote è necessario nel caso in cui la tua emoticon contenga caratteri speciali regex.

Inoltre, un formato migliore potrebbe essere:

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

Poi si può ciclo su tutto.


Aggiornamento

dovrebbero usare lookarounds negativi invece per abbinare emoticon side-by-side. Quindi non tenterà di abbinare gli spazi circostanti.

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

Inoltre, cercano di usare le virgolette singole durante la scrittura di modelli regex, perché virgolette consentono sequenze di escape, e apici non interpreteranno sequenza di escape. Ad esempio, a volte è necessario raddoppiare le barre quando si utilizzano le virgolette doppie.

+0

'Preg_quote' accetta un array? In caso contrario, scrivere un metodo che scorre attraverso l'array e restituisce l'array di escape con il pattern circostante. – Josh

+1

@Josh: No, non è così. http://ca.php.net/manual/en/function.preg-quote.php. Puoi anche mettere tutti i "sorrisi" in una singola regex implorandoli con una pipe (dopo che sono preg-quotati). La stringa finale dovrebbe essere simile a: '# (^ | \ W) (: - \) |: \) |>: \]) ($ | \ W) #' – mpen

+0

Vero, allora sarà solo logicamente OR attraverso ogni modello. Bella soluzione Lo aggiungerei alla tua risposta. – Josh

0

Forse hanno un ciclo di formattazione come

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

allora è solo una goccia per preg_replace ($ sorrisi, $ t_smiles, $ testo)

0

Qualcosa in questo senso è probabilmente quello che stai cercando:

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

Inoltre, come segno di detto, si sarebbe meglio di una serie gigantesca di tutte le emoticon di un centinaio di piccole variabili che sono state trattare manualmente.

+0

non funzionano qui. Credo che ci sia un carattere word su un lato e un carattere non word su l'altro: le '': 's and') 's nelle faccine non sono caratteri di parole, quindi' \ b' non corrisponderebbe a nulla in una stringa come '" :) "' ad esempio (spazi su entrambi i lati). in realtà, * corrisponderebbe * a x:) 'che è l'esatto contrario di ciò che vogliamo. – mpen