El orden de LC_COLLATEclasificació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, Bno 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, Bse encuentra, ya que el rango a-zincluye todo lo que está entre ay zen el orden de clasificación, incluyendo las mayúsculas Ba través Z.
Todos los sistemas probados tienen la en_USconfiguración regional generada. También intenté variar la configuración regional: en las máquinas en las que Bse 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_USconfiguraciones 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 Bestá adentro [a-z]y otra donde no está, la salida de LC_COLLATE=en_US locale -k LC_COLLATEes
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_COLLATEes
collate-nrules=4
collate-rulesets=""
collate-symb-hash-sizemb=2039
collate-codeset="UTF-8"
fuente

en_USembargo, no se verificó si se genera.Centorno local se utiliza como reserva y su orden de clasificación es de valores de bytes directos, porBlo 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
Cconfiguració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
Cconfiguración regional, que siempre está disponible:Si esto no funciona como se esperaba, realmente es un error.
fuente
locale -kmi pregunta; Es idéntico en dos máquinas Debian, una dondeBestá 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:]]'devuelveaYü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 OPCconfiguración regional. Creo que esto es relevante para el OP, que estaba buscando reportar un error. Si no está en laCconfiguració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 laCconfiguració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íaBdar 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.