2009-09-20 9 views
11

che sto cercando di fare la sostituzione carattere accentato in PHP, ma ottenere risultati funky, la mia ipotesi che sono perché sto utilizzando uno stringa UTF-8 e str_replace non riesco a gestire correttamente le stringhe multi-byte ..PHP Multi Byte str_replace?

$accents_search  = array('á','à','â','ã','ª','ä','å','Á','À','Â','Ã','Ä','é','è', 
'ê','ë','É','È','Ê','Ë','í','ì','î','ï','Í','Ì','Î','Ï','œ','ò','ó','ô','õ','º','ø', 
'Ø','Ó','Ò','Ô','Õ','ú','ù','û','Ú','Ù','Û','ç','Ç','Ñ','ñ'); 

$accents_replace = array('a','a','a','a','a','a','a','A','A','A','A','A','e','e', 
'e','e','E','E','E','E','i','i','i','i','I','I','I','I','oe','o','o','o','o','o','o', 
'O','O','O','O','O','u','u','u','U','U','U','c','C','N','n'); 

$str = str_replace($accents_search, $accents_replace, $str); 

risultati che ottengo:

Ørjan Nilsen -> �orjan Nilsen 

Risultato previsto:

Ørjan Nilsen -> Orjan Nilsen 

Edit: ho ottenuto il mio gestore di carattere interno impostato su UTF-8 (secondo mb_interna l_encoding()), anche il valore di $ str è UTF-8, quindi da quello che posso dire, tutte le stringhe coinvolte sono UTF-8. Str_replace() rileva i set di caratteri e li usa correttamente?

+0

Controlla la mia risposta qui: [Correggi i caratteri in PHP] (http://stackoverflow.com/a/9499771/318380). Questo mi ha aiutato molto !!! – jazkat

risposta

5

Sembra che la stringa non sia stata sostituita perché la codifica dell'input e la mancata corrispondenza della codifica del file.

+0

Aye, il file UTF-8 eseguito su cli in un file di testo (non viene emesso sul terminale iso) funziona. – OIS

+0

Quindi, come posso modificare la mia codifica Input, quindi? – Ian

+0

Ho controllato il mio editor di testo, la sua codifica dei file è impostata su UTF-8. – Ian

2

Prova questa definizione di funzione:

if (!function_exists('mb_str_replace')) { 
    function mb_str_replace($search, $replace, $subject) { 
     if (is_array($subject)) { 
      foreach ($subject as $key => $val) { 
       $subject[$key] = mb_str_replace((string)$search, $replace, $subject[$key]); 
      } 
      return $subject; 
     } 
     $pattern = '/(?:'.implode('|', array_map(create_function('$match', 'return preg_quote($match[0], "/");'), (array)$search)).')/u'; 
     if (is_array($search)) { 
      if (is_array($replace)) { 
       $len = min(count($search), count($replace)); 
       $table = array_combine(array_slice($search, 0, $len), array_slice($replace, 0, $len)); 
       $f = create_function('$match', '$table = '.var_export($table, true).'; return array_key_exists($match[0], $table) ? $table[$match[0]] : $match[0];'); 
       $subject = preg_replace_callback($pattern, $f, $subject); 
       return $subject; 
      } 
     } 
     $subject = preg_replace($pattern, (string)$replace, $subject); 
     return $subject; 
    } 
} 
+0

forse ho sbagliato, ma sembra che lo schema corretto sarebbe: ''/ ('. Preg_quote (implode ('', (array) $ search), '/').')/ u'' ?? – Igor

3

E 'possibile rimuovere i segni diacritici che utilizzano Unicode normalization form D (NFD) e proprietà dei caratteri Unicode.

NFD converte qualcosa come l'umlaut "ü" da "LATIN SMALL LETTER U WITH DIAERESIS" (che è una lettera) a "LATIN SMALL LETTER U" (lettera) e "COMBINING DIAERESIS" (non una lettera).

header('Content-Type: text/plain; charset=utf-8'); 

$test = implode('', array('á','à','â','ã','ª','ä','å','Á','À','Â','Ã','Ä','é','è', 
'ê','ë','É','È','Ê','Ë','í','ì','î','ï','Í','Ì','Î','Ï','œ','ò','ó','ô','õ','º','ø', 
'Ø','Ó','Ò','Ô','Õ','ú','ù','û','Ú','Ù','Û','ç','Ç','Ñ','ñ')); 

$test = Normalizer::normalize($test, Normalizer::FORM_D); 

// Remove everything that's not a "letter" or a space (e.g. diacritics) 
// (see http://de2.php.net/manual/en/regexp.reference.unicode.php) 
$pattern = '/[^\pL ]/u'; 

echo preg_replace($pattern, '', $test); 

uscita:

aaaaªaaAAAAAeeeeEEEEiiiiIIIIœooooºøØOOOOuuuUUUcCNn 

classe Il normalizzatore fa parte della PECL intl package. (L'algoritmo in sé non è molto complicato ma ha bisogno di caricare un sacco di mappature dei caratteri afaik. Ho scritto un PHP implementation qualche tempo fa.)

(Sto aggiungendo questo ritardo di due mesi perché penso che sia una bella tecnica che è non noto abbastanza ampiamente.)

+0

Grazie, è davvero piuttosto utile. Anche se in realtà non voglio usarlo in questo caso perché si traduce nella perdita di accenti. – Ian

+3

Pensavo che eliminare gli accenti fosse ciò che stavi cercando di fare? – mermshaus

16

In base alla documentazione php str_replace la funzione è a prova di binario, il che significa che può gestire il testo codificato UTF-8 senza alcuna perdita di dati.

+0

Grazie, dav. Questa dovrebbe essere la risposta corretta, perché spiega perché ci sono mb_substr() e mb_strlen() ma non mb_str_replace(). Le prime due funzioni usano (o restituiscono) posizioni di offset per caratteri di testo (che dipendono dalla codifica del testo) mentre str_replace() no. Ecco perché str_replace() può lavorare con i dati UTF-8 in modo sicuro (o qualsiasi altra codifica Unicode o in genere con dati binari). – StanE