L' ordre de LC_COLLATE
classement via définit non seulement l'ordre de tri des caractères individuels, mais également la signification des plages de caractères. Ou alors? Considérez l'extrait de code suivant:
unset LANGUAGE LC_ALL
echo B | LC_COLLATE=en_US grep '[a-z]'
Intuitivement, B
n'est pas dedans, [a-z]
donc cela ne devrait rien produire. C'est ce qui se passe sur Ubuntu 8.04 ou 10.04. Mais sur certaines machines en cours d' exécution ou de Debian Squeeze, B
se trouve, parce que la gamme a-z
comprend tout ce qui est entre a
et z
dans l'ordre de classement, y compris les lettres majuscules B
par Z
.
Tous les systèmes testés ont en_US
généré les paramètres régionaux. J'ai également essayé de faire varier les paramètres régionaux: sur les machines où B
est comparé 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 dans 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 , lorsque 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 contre qui un bug devrait-il être signalé?
(Notez que je pose spécifiquement des questions sur le comportement des plages de caractères telles que [a-z]
dans les en_US
locales, principalement sur les systèmes basés sur la libc GNU. Je ne demande pas comment faire correspondre les lettres minuscules ou les lettres minuscules ASCII.)
Sur deux machines Debian, une où se B
trouve [a-z]
et une où elle ne l'est pas, 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"
la source
en_US
est généré, cependant.C
paramètres régionaux sont utilisés comme solution de repli et leur ordre de classement est des valeurs d'octets droits, doncB
ils ne seront pas mis en correspondance. Testez dans un environnement local qui apparaît dans la sortie delocale -a
.Réponses:
Si vous utilisez autre chose que les
C
paramètres régionaux, vous ne devez pas utiliser des plages comme[a-z]
celles-ci car elles dépendent des paramètres régionaux et ne donnent pas toujours les résultats attendus. En plus du problème de cas que vous avez déjà rencontré, certains paramètres régionaux traitent les caractères avec des signes diacritiques (par exemple á ) de la même manière que le caractère de base (c'est -à- dire a ).Utilisez plutôt une classe de caractères nommée:
Cela donnera toujours le résultat correct pour les paramètres régionaux. Cependant, vous devez choisir les paramètres régionaux pour refléter la signification de votre texte d'entrée et du test que vous essayez d'appliquer.
Par exemple, si vous devez trouver une valeur d'octet particulière, utilisez les
C
paramètres régionaux, qui sont toujours disponibles:Si cela ne fonctionne pas comme prévu, c'est vraiment un bug.
la source
locale -k
à ma question; il est identique sur deux machines Debian, une où elleB
est dans la plage et une où elle ne l'est pas. BTW, je ne suis root sur aucune des deux machines (donc ce n'est pas quelque chose de particulier que je fais en tant qu'administrateur).echo "Baü" | LC_COLLATE=C grep -o '[[:lower:]]'
renvoiea
ETü
tandis queecho "Baü" | LC_COLLATE=C grep -o '[a-z]'
renvoie uniquementa
. À mes yeux, "plus bas" n'est pas vraiment ce que le PO voulaitC
paramètres régionaux. Je pense que cela concerne le PO, qui cherchait à signaler un bug. Si vous n'êtes pas dans leC
paramètres régionaux, les résultats de l'utilisation des plages sont très imprévisibles et ne peuvent donc jamais être considérés comme un bogue. D'un autre côté, si vous avez besoin de trouver une valeur d'octet particulière, utilisez simplement lesC
paramètres régionaux. Mon point secondaire était que si vous voulez vraiment rechercher des lettres minuscules dans un environnement local, utilisez une classe de caractères. Même si le PO ne l'a peut-être pas recherché, d'autres le pourraient s'ils trouvent cette question.Les plages dans les expressions régulières doivent respecter le paramètre de classement. Voici la norme pertinente: http://pubs.opengroup.org/onlinepubs/007908799/xbd/re.html (recherchez les "expressions de plage"). La
echo B | LC_COLLATE=en_US grep '[a-z]'
sortie devrait doncB
donner une définition raisonnable des paramètres régionaux respectifs. Je ne peux pas expliquer pourquoi cela ne fonctionne parfois pas pour vous, mais je serais très surpris si je rencontrais cela sur un système non ancien correctement installé et configuré.la source
echo B | LC_COLLATE=en_US.utf8 grep '[a-z]'
N'imprime rien sur Ubuntu 12.04 avec grep 2.10. N'imprime rien sur Centos 6.5 avec grep 2.6.3. Fonctionne sur Debian 6.0.8 avec grep 2.6.3.