Ordre de classement via LC_COLLATE
définit non seulement l'ordre de tri des caractères individuels, mais également la signification des plages de caractères. Ou le fait-il? Considérez l'extrait suivant :
unset LANGUAGE LC_ALL
echo B | LC_COLLATE=en_US grep '[a-z]'
Intuitivement, B
n'est pas dans [a-z]
, donc cela ne devrait rien afficher. C'est ce qui se passe sur Ubuntu 8.04 ou 10.04. Mais sur certaines machines exécutant Debian lenny ou squeeze, B
est trouvé, car la plage a-z
inclut tout ce qui est entre a
et z
dans l'ordre de classement, y compris les majuscules B
par Z
.
Tous les systèmes testés ont le en_US
paramètres régionaux générés. J'ai également essayé de varier les paramètres régionaux :sur les machines où B
correspond ci-dessus, la même chose se produit dans tous les paramètres régionaux disponibles (principalement en latin :{en_{AU,CA,GB,IE,US},fr_FR,it_IT,es_ES,de_DE}{iso8859-1,iso8859-15,utf-8}
, également les paramètres régionaux chinois) sauf le japonais (dans n'importe quel encodage disponible) et C
/POSIX
.
Que signifient les plages de caractères dans les expressions régulières , quand vous allez au-delà de l'ASCII ? Pourquoi y a-t-il une différence entre certaines installations Debian d'une part, et d'autres installations Debian et Ubuntu d'autre part ? Comment se comportent les autres systèmes ? Qui a raison et à qui doit-on signaler un bogue ?
(Notez que je pose spécifiquement des questions sur le comportement des plages de caractères telles que [a-z]
en en_US
locales, principalement sur les systèmes basés sur GNU libc. Je ne demande pas comment faire correspondre les lettres minuscules ou les lettres minuscules ASCII.)
Sur deux machines Debian, une où B
est en [a-z]
et une où ce n'est pas le cas, la sortie de LC_COLLATE=en_US locale -k LC_COLLATE
est
collate-nrules=4
collate-rulesets=""
collate-symb-hash-sizemb=1
collate-codeset="ISO-8859-1"
et la sortie de LC_COLLATE=en_US.utf8 locale -k LC_COLLATE
est
collate-nrules=4
collate-rulesets=""
collate-symb-hash-sizemb=2039
collate-codeset="UTF-8"
Réponse acceptée :
Si vous utilisez autre chose que le C
locale, vous ne devriez pas utiliser des plages comme [a-z]
car ceux-ci dépendent des paramètres régionaux et ne donnent pas toujours les résultats que vous attendez. En plus du problème de casse que vous avez déjà rencontré, certains paramètres régionaux traitent les caractères avec des signes diacritiques (par exemple, á ) identique au caractère de base (c'est-à-dire a ).
Utilisez plutôt une classe de caractères nommée :
echo B | grep '[[:lower:]]'
Cela donnera toujours le résultat correct pour la locale. Cependant, vous devez choisir les paramètres régionaux pour refléter la signification à la fois de votre texte d'entrée et du test que vous essayez d'appliquer.
Connexe :Php :imagechar — Dessine un personnage horizontalement
Par exemple, si vous avez besoin de trouver une valeur d'octet particulière, utilisez le C
locale, qui est toujours disponible :
echo B | LANG=C grep '[a-z]'
Si cela ne fonctionne pas comme prévu, c'est vraiment un bug.