El orden de LC_COLLATE
clasificación define no solo el orden de clasificación de los caracteres individuales, sino también el significado de los rangos de caracteres. O lo hace? Considere el siguiente fragmento:
unset LANGUAGE LC_ALL
echo B | LC_COLLATE=en_US grep '[a-z]'
Intuitivamente, B
no está dentro [a-z]
, por lo que esto no debería generar nada. Eso es lo que sucede en Ubuntu 8.04 o 10.04. Sin embargo, en algunas máquinas que ejecutan Lenny Debian o apretón, B
se encuentra, ya que el rango a-z
incluye todo lo que está entre a
y z
en el orden de clasificación, incluyendo las mayúsculas B
a través Z
.
Todos los sistemas probados tienen la en_US
configuración regional generada. También intenté variar la configuración regional: en las máquinas en las que B
se hace coincidir anteriormente, sucede lo mismo en todas las configuraciones regionales disponibles (en su mayoría basadas en latín {en_{AU,CA,GB,IE,US},fr_FR,it_IT,es_ES,de_DE}{iso8859-1,iso8859-15,utf-8}
, también en configuraciones regionales chinas), excepto en japonés (en cualquier codificación disponible) y C
/ POSIX
.
¿Qué significan los rangos de caracteres en las expresiones regulares , cuando vas más allá de ASCII? ¿Por qué hay una diferencia entre algunas instalaciones de Debian por un lado, y otras instalaciones de Debian y Ubuntu por el otro? ¿Cómo se comportan otros sistemas? ¿Quién tiene razón y contra quién se debe informar un error?
(Tenga en cuenta que estoy preguntando específicamente sobre el comportamiento de los rangos de caracteres, como [a-z]
en las en_US
configuraciones regionales, principalmente en los sistemas basados en GNU libc. No estoy preguntando cómo hacer coincidir letras minúsculas o minúsculas ASCII).
En dos máquinas Debian, una donde B
está adentro [a-z]
y otra donde no está, la salida de LC_COLLATE=en_US locale -k LC_COLLATE
es
collate-nrules=4
collate-rulesets=""
collate-symb-hash-sizemb=1
collate-codeset="ISO-8859-1"
y la salida de LC_COLLATE=en_US.utf8 locale -k LC_COLLATE
es
collate-nrules=4
collate-rulesets=""
collate-symb-hash-sizemb=2039
collate-codeset="UTF-8"
fuente
en_US
embargo, no se verificó si se genera.C
entorno local se utiliza como reserva y su orden de clasificación es de valores de bytes directos, porB
lo que no coincidirá. Pruebe en un entorno local que aparezca en la salida delocale -a
.Respuestas:
Si está utilizando otra cosa que no sea la
C
configuración regional, no debería utilizar rangos como[a-z]
estos, ya que dependen de la configuración regional y no siempre dan los resultados esperados. Además del problema de caso que ya ha encontrado, algunos entornos locales tratan los caracteres con signos diacríticos (por ejemplo, á ) igual que el carácter base (es decir, a ).En su lugar, use una clase de caracteres con nombre:
Esto siempre dará el resultado correcto para la configuración regional. Sin embargo, debe elegir la configuración regional para reflejar el significado tanto del texto de entrada como de la prueba que está intentando aplicar.
Por ejemplo, si necesita encontrar un valor de byte particular, use la
C
configuración regional, que siempre está disponible:Si esto no funciona como se esperaba, realmente es un error.
fuente
locale -k
mi pregunta; Es idéntico en dos máquinas Debian, una dondeB
está dentro del rango y otra donde no está. Por cierto, no soy root en ninguna de las máquinas (por lo que no es algo peculiar que hago como administrador).echo "Baü" | LC_COLLATE=C grep -o '[[:lower:]]'
devuelvea
Yü
mientras queecho "Baü" | LC_COLLATE=C grep -o '[a-z]'
solo regresaa
. En mi opinión, "bajar" no es realmente lo que quería el OPC
configuración regional. Creo que esto es relevante para el OP, que estaba buscando reportar un error. Si no está en laC
configuración regional, los resultados del uso de rangos son altamente impredecibles y, por lo tanto, nunca se pueden considerar un error. Por otro lado, si necesita encontrar un valor de byte particular, simplemente use laC
configuración regional. Mi punto secundario fue que si realmente desea buscar letras minúsculas en una configuración regional, use una clase de caracteres. Aunque el OP puede no haber estado buscando esto, otros podrían hacerlo si encuentran esta pregunta.Los rangos en expresiones regulares deben observar la configuración de intercalación. Aquí está el estándar relevante: http://pubs.opengroup.org/onlinepubs/007908799/xbd/re.html (busque "expresiones de rango"). Por
echo B | LC_COLLATE=en_US grep '[a-z]'
lo tanto, deberíaB
dar una definición razonable de la configuración regional respectiva. No puedo explicar por qué esto a veces no funciona para ti, pero me sorprendería mucho si me encontrara con un sistema no antiguo que esté instalado y configurado correctamente.fuente
echo B | LC_COLLATE=en_US.utf8 grep '[a-z]'
No imprime nada en Ubuntu 12.04 con grep 2.10. No imprime nada en Centos 6.5 con grep 2.6.3. Funciona en Debian 6.0.8 con grep 2.6.3.