2009-09-20 23 views
11

estoy tratando de hacer sustitución de caracteres acentuados en PHP, pero obtener resultados cobardes, siendo yo creo porque estoy usando una cadena UTF-8 y str_replace no pueda manejar adecuadamente cadenas multibyte ..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); 

resultados que obtengo:

Ørjan Nilsen -> �orjan Nilsen 

Resultado esperado:

Ørjan Nilsen -> Orjan Nilsen 

Editar: tengo mi manejador de carácter interno establece en UTF-8 (de acuerdo con mb_interna l_encoding()), también el valor de $ str es UTF-8, por lo que puedo decir, todas las cadenas involucradas son UTF-8. ¿Str_replace() detecta los conjuntos de caracteres y los usa correctamente?

+0

Compruebe mi respuesta aquí: [Corregir caracteres en PHP] (http://stackoverflow.com/a/9499771/318380). ¡¡¡Esto me ayudó mucho!!! – jazkat

Respuesta

5

Parece que la cadena no se ha reemplazado porque la codificación de entrada y la codificación del archivo no coinciden.

+0

Sí, se ejecuta el archivo UTF-8 en cli a un archivo de texto (no se da salida a la terminal iso). – OIS

+0

Entonces, ¿cómo puedo cambiar mi codificación de entrada? – Ian

+0

Revisé mi editor de texto, su codificación de archivo está configurada en UTF-8. – Ian

2

probar este definición de función:

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

tal vez me he equivocado, pero parece que el patrón correcto sería: ''/ ('. Preg_quote (implode ('', (matriz) $ search), '/').')/ u'' ?? – Igor

3

Es posible eliminar los signos diacríticos utilizando Unicode normalization form D (NFD) y propiedades de caracteres Unicode.

NFD convierte algo así como la "ü" diéresis "de" LETRA U MINÚSCULA LATINA CON DIAESIS "(que es una letra) a" LETRA U MINÚSCULA LATINA "(letra) y" DIAESIS COMBINADA "(no una letra).

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

Salida:

aaaaªaaAAAAAeeeeEEEEiiiiIIIIœooooºøØOOOOuuuUUUcCNn 

clase El Normalizador es parte de la PECL intl package. (El algoritmo en sí no es muy complicado, pero necesita cargar muchas asignaciones de caracteres afaik. Hace un tiempo escribí PHP implementation)

(Estoy agregando esto dos meses tarde porque creo que es una buena técnica que es no conocido ampliamente.)

+0

Gracias, eso es bastante útil. Aunque realmente no quiero usar eso en este caso porque da como resultado la pérdida de acentos. – Ian

+3

Pensé que deshacerse de los acentos era lo que intentabas hacer? – mermshaus

16

Según la documentación de php str_replace la función es binaria segura, lo que significa que puede manejar el texto codificado UTF-8 sin pérdida de datos.

+0

Gracias, dav. Esta debería ser la respuesta correcta, porque explica por qué hay mb_substr() y mb_strlen() pero no mb_str_replace(). Las primeras dos funciones usan (o regresan) posiciones de desplazamiento para caracteres de texto (que depende de la codificación del texto) mientras que str_replace() no. Es por eso que str_replace() puede funcionar con datos UTF-8 de forma segura (o cualquier otra codificación Unicode o generalmente con datos binarios). – StanE