Pregunta

Me comenzó con algunos fallos locos utilizando preg_replace en php y se hierve abajo al caso problema de tener más de una clase de caracteres usando turco de puntos "i" y sin punto "i" juntos. Aquí está una prueba simple en PHP:

<?php
    echo 'match single normal i: ';
    $str = 'mi';
    echo (preg_match('!m[ıi]!', $str)) ? "ok\n" : "fail\n";

    echo 'match single undotted ı: ';
    $str = 'mı';
    echo (preg_match('!m[ıi]!', $str)) ? "ok\n" : "fail\n";

    echo 'match double normal i: ';
    $str = 'misir';
    echo (preg_match('!m[ıi]s[ıi]r!', $str)) ? "ok\n" : "fail\n";

    echo 'match double undotted ı: ';
    $str = 'mısır';
    echo (preg_match('!m[ıi]s[ıi]r!', $str)) ? "ok\n" : "fail\n";
?>

Y el mismo caso de prueba de nuevo en Perl:

#!/usr/bin/perl

$str = 'mi';
$str =~ m/m[ıi]/ && print "match single normal i\n";

$str = 'mı';
$str =~ m/m[ıi]/ && print "match single undotted ı\n";

$str = 'misir';
$str =~ m/m[ıi]s[ıi]r/ && print "match double normal i\n";

$str = 'mısır';
$str =~ m/m[ıi]s[ıi]r/ && print "match double undotted ı\n";

El primer trabajo de tres pruebas bien. El último no coincide.

¿Por qué este trabajo fino como una clase de caracteres vez, pero no la segunda vez en la misma expresión? ¿Cómo se escribe una expresión para que coincida con una palabra como ésta, que debe coincidir con no importa qué combinaciones de letras está escrito con?

Editar el problema del idioma estoy tratando de programa de.

Editar 2: Adición de una directiva use utf8; hace fijar la versión de Perl. Desde mi problema original con un programa php y sólo cambió a Perl para ver si se trataba de un fallo en PHP, eso no me ayuda mucho. ¿Alguien sabe la directiva para que PHP no ahogarse con esto?

¿Fue útil?

Solución

secuencias de varios bytes no va a hacer lo que quiere en clases de char entre corchetes si el UTF-8 es ser mis-interpretado como una secuencia de bytes de 8 bits. Piénsalo. Si se [nñm] misconstructed no como tres caracteres lógicos sino como cuatro bytes físicos, sólo se correspondería con un personaje cuyo punto de código es 6E o C3 o B1 o 6D.

Para algunos propósitos, es posible salirse con la reescritura [nñm] como (?:n|ñ|m). Sólo depende de lo que está haciendo. cosas de la carcasa no funcionará.

Además, Unicode tiene reglas especiales para una carcasa sin punto turca i.

Sonidos como PHP simplemente no es lo suficientemente moderno. Suspiro.

Otros consejos

Se puede necesitar decirle Perl que el archivo de origen contiene caracteres UTF8. Proveedores:

#!/usr/bin/perl

use utf8;   # **** Add this line

$str = 'mısır';
$str =~ m/m[ıi]s[ıi]r/ && print "match double undotted ı\n";

Lo que no le ayuda con PHP, pero puede haber una directiva similar en PHP. De lo contrario, trate de usar alguna forma de escapar de secuencia para evitar poner el carácter literal en su código fuente. No sé nada de PHP, así que no puede ayudar con eso.

Editar
Estoy leyendo que PHP no tiene soporte Unicode. Por lo tanto, la entrada de Unicode se le pasa es probable tratado como la cadena de bytes que el Unicode se codifican como.

Si usted puede estar seguro de que su entrada está entrando como UTF-8, entonces puede coincidir con la secuencia de codificación UTF-8 para ı que es \xc4 \xb1 como en:

$str = 'mısır';  # Make sure this source-file is encoded as utf-8 or this match will fail
echo (preg_match('!m(i|\xc4\xb1)s(i|\xc4\xb1)r!', $str)) ? "ok\n" : "fail\n";

funciona eso?

Editar de nuevo:
Puedo explicar por qué pasan sus tres primeras pruebas. Supongamos que en su codificación, ı se codifica como ABCDE. entonces PHP ve el siguiente:

echo 'match single normal i: ';
$str = 'mi';
echo (preg_match('!m[ABCDEi]!', $str)) ? "ok\n" : "fail\n";

echo 'match single undotted ABCDE: ';
$str = 'mABCDE';
echo (preg_match('!m[ABCDEi]!', $str)) ? "ok\n" : "fail\n";

echo 'match double normal i: ';
$str = 'misir';
echo (preg_match('!m[ABCDEi]s[ABCDEi]r!', $str)) ? "ok\n" : "fail\n";

echo 'match double undotted ABCDE: ';
$str = 'mABCDEsABCDEr';
echo (preg_match('!m[ABCDEi]s[ABCDEi]r!', $str)) ? "ok\n" : "fail\n";

lo que hace evidente por qué las tres primeras pruebas pasan y la última falla. Si se utiliza un anclaje ^...$ inicio / final, creo que usted encontrará que sólo la primera prueba pasa.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top