2009-09-20 15 views
11

Ich versuche Umlaut Ersatz in PHP zu tun, aber flippige Ergebnisse zu erhalten, ist meine Vermutung, weil ich bin ein UTF-8-String und str_replace verwenden, können Multi-Byte-Strings nicht richtig handhaben ..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); 

Ergebnisse erhalte ich:

Ørjan Nilsen -> �orjan Nilsen 

Erwartetes Ergebnis:

Ørjan Nilsen -> Orjan Nilsen 

Edit: ich habe meine interne Zeichen Handler auf UTF-8 erhielt (nach mb_interna l_encoding()), auch der Wert von $ str ist UTF-8, von dem was ich sagen kann, sind alle beteiligten Strings UTF-8. Erkennt str_replace() Zeichensätze und verwendet sie richtig?

+0

Überprüfen Sie meine Antwort hier: [Fix Zeichen in PHP] (http://stackoverflow.com/a/9499771/318380). Das hat mir sehr geholfen !!! – jazkat

Antwort

5

Sieht aus wie die Zeichenfolge wurde nicht ersetzt, da Ihre Eingabe Codierung und die Datei Codierung nicht übereinstimmen.

+0

Aye, UTF-8-Datei läuft auf CLI zu einer Textdatei (dont Ausgabe an ISO-Terminal) funktioniert. – OIS

+0

Also, wie kann ich dann meine Eingabecodierung ändern? – Ian

+0

Ich habe meinen Texteditor überprüft, die Dateikodierung ist auf UTF-8 eingestellt. – Ian

2

diese Funktion Definition Versuchen: mit Unicode normalization form D (NFD) und Unicode-Zeicheneigenschaften

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

vielleicht habe ich mich geirrt, aber es scheint das richtige Muster wäre: ''/ ('. Preg_quote (implode ('', (array) $ search), '/'.')/ u'' ?? – Igor

3

es möglich ist, diakritische Zeichen zu entfernen.

NFD konvertiert etwas wie den "ü" Umlaut von "LATIN KLEINER BRIEF MIT DIAERESE" (was ein Brief ist) zu "LATIN KLEINER BRIEF U" (Brief) und "KOMBINIEREND DIAERESE" (kein Brief).

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

Ausgang:

aaaaªaaAAAAAeeeeEEEEiiiiIIIIœooooºøØOOOOuuuUUUcCNn 

Die Normalizer-Klasse ist Teil des PECL intl package. (Der Algorithmus selbst ist nicht sehr kompliziert, aber muss eine Menge Character Mappings afaik laden. Ich schrieb eine PHP implementation vor einer Weile.)

(Ich füge diese zwei Monate spät hinzu, weil ich denke, dass es eine nette Technik ist, die ist nicht weit genug bekannt.)

+0

Danke, das ist eigentlich ziemlich nützlich. Obwohl ich das in diesem Fall nicht wirklich verwenden möchte, weil es zum Verlust von Akzenten führt. – Ian

+3

Ich dachte, dass Akzente loszuwerden, was Sie versuchten zu tun? – mermshaus

16

Laut php Dokumentation str_replace Funktion ist binär-sicher, was bedeutet, dass es UTF-8 codierten Text ohne Datenverlust verarbeiten kann.

+0

Danke, dav. Dies sollte die richtige Antwort sein, weil es erklärt, warum es mb_substr() und mb_strlen(), aber nicht mb_str_replace() gibt. Die ersten beiden Funktionen verwenden (oder liefern) Offsetpositionen für Textzeichen (die von der Textcodierung abhängen), während str_replace() nicht verwendet wird. Aus diesem Grund kann str_replace() sicher mit UTF-8-Daten arbeiten (oder mit anderen Unicode-Kodierungen oder allgemein mit binären Daten). – StanE