Sensibilité à la casse dans le globbing entre crochets

10

Normalement, bash globbing est sensible à la casse:

$ echo c*
casefix.pike cdless chalices.py charconv.py chocolate.pike circum.py clip.pike cpustats.pike crop.pike cwk2txt.py
$ echo C*
CarePackage.md ChocRippleCake.md Clips

L'utilisation de crochets ne semble pas changer cela:

$ echo [c]*
casefix.pike cdless chalices.py charconv.py chocolate.pike circum.py clip.pike cpustats.pike crop.pike cwk2txt.py
$ echo [C]*
CarePackage.md ChocRippleCake.md Clips

Il ne le change toujours pas si un trait d'union est utilisé:

$ echo [c-c]*
casefix.pike cdless chalices.py charconv.py chocolate.pike circum.py clip.pike cpustats.pike crop.pike cwk2txt.py
$ echo [C-C]*
CarePackage.md ChocRippleCake.md Clips

Mais les lettres sont entrecoupées:

$ echo [B-C]*
CarePackage.md casefix.pike cdless chalices.py charconv.py chocolate.pike ChocRippleCake.md circum.py clip.pike Clips cpustats.pike crop.pike cwk2txt.py
$ echo [b-c]*
beehive-anthem.txt bluray2mkv.pike branch branchcleanup.pike burdayim.pike casefix.pike cdless chalices.py charconv.py chocolate.pike circum.py clip.pike cpustats.pike crop.pike cwk2txt.py

Cela suggère que le tiret utilise un ordre de paramètres régionaux, "AaBbCcDd". Donc: existe-t-il un moyen de globaliser tous les fichiers commençant par une lettre majuscule?

rosuav
la source
3
Notez également le gotcha qui [AZ] correspond à toutes les lettres minuscules sauf «z»!
PJTraill

Réponses:

12

Dans la version 4.3 et ultérieure de bash, il existe une option shopt appelée globasciiranges:

Selon les pages de manuel de shopt builtin gnu :

globasciiranges
Si elles sont définies, les expressions de plage utilisées dans les expressions de parenthèse de correspondance de motifs (voir Correspondance de motifs) se comportent comme si dans les paramètres régionaux C traditionnels lors des comparaisons. C'est-à-dire que la séquence de classement des paramètres régionaux actuels n'est pas prise en compte, donc «b» ne collationnera pas entre «A» et «B», et les caractères ASCII majuscules et minuscules seront collationnés ensemble.

En conséquence, vous pouvez

$ shopt -s globasciiranges 
$ echo [A-Z]*

Utilisez shopt -upour désactiver.

Une autre façon est de changer les paramètres régionaux en C. Vous pouvez le faire temporairement en utilisant un sous-shell:

$ ( LC_ALL=C ; printf '%s\n' [A-Z]*; )

Vous obtiendrez les résultats dont vous avez besoin, et lorsque le sous-shell est terminé, les paramètres régionaux de votre shell principal restent inchangés par rapport à ce qui était auparavant.

Une autre alternative consiste [A-Z]à utiliser l'expansion d'accolade {A..Z}avec l' nullgloboption bash shopt.

En activant l' nullgloboption, si un modèle n'est pas mis en correspondance pendant l'expansion du nom de chemin, une chaîne nulle est renvoyée à la place du modèle lui-même.
En conséquence, celui-ci fonctionnera comme prévu:

$ shopt -s nullglob;printf '%s\n' {A..Z}*
George Vasiliou
la source
2
Parfait merci. Je ne peux pas l'utiliser [[:upper:]]parce que je veux juste une partie de l'alphabet, mais cela fonctionne.
rosuav
1
@rosuav Bienvenue. Vérifiez également l'alternative au sous-shell.
George Vasiliou
"Si activé est égal aux paramètres régionaux C" - voulez-vous dire que cela affecte les paramètres régionaux utilisés pour la globalisation et rien d'autre? (Un lien de référence aurait été utile - le meilleur que je puisse trouver est gnu.org/software/bash/manual/html_node/Pattern-Matching.html , mais j'aurais préféré une liste de toutes les options du shell, mais globasciiranges est manquant sur gnu.org/software/bash/manual/html_node/… ; la question unix.stackexchange.com/questions/227070/… traite également ce problème de manière approfondie.) Également à partir de la version 4.3.
PJTraill
@PjTrail Voir ma modification avec un lien de référence vers toutes les options de shopt. Vous pouvez également exécuter man bashdans votre terminal et rechercher (en utilisant /) des globasciiranges.
George Vasiliou
Ne LC_ALL=C printf '%s\n' [A-Z]*fonctionnerait pas pour votre deuxième solution - sans sous-coque? BTW: il y a une faute de frappe:, nullblogmais c'est trop peu de caractères pour que je puisse la corriger.
Joe
5

Vous pouvez très bien écrire toutes les lettres majuscules comme:

[ABCDEFGHIJKLMNOPQRSTUVWXYZ]*

ou use peut utiliser la classe de caractères nommée [:upper:]pour représenter toutes les lettres majuscules dans votre courant locale:

[[:upper:]]*

Comme vous l'avez remarqué, tout en utilisant la plage comme [B-C]les majuscules et les minuscules pour le même caractère alphabétique sont disposés de manière adjacente (selon l'ordre de classement du locale).

heemayl
la source
3

L'inclusion de caractères «non intuitifs» dans les plages de caractères, comme l'inclusion de lettres minuscules dans une plage dont les limites sont des lettres majuscules, est due au LC_COLLATEparamètre local. LC_COLLATEest censé indiquer l'ordre de tri, mais il le fait mal (le tri des chaînes est plus complexe que ce que les locales peuvent faire) et il vaut mieux s'en passer. Je recommande de supprimer LC_COLLATEde vos paramètres régionaux. Si vous configurez LANG, ou LANGUAGE, ne pas le faire et mettre uniquement ceux dont vous avez besoin: LC_CTYPE, LC_MESSAGES, LC_TIME.

Pour plus d'informations sur les paramètres régionaux, voir À quoi dois-je définir mes paramètres régionaux et quelles en sont les implications? et définissez LC_ * mais pas LC_ALL

Pour obtenir des résultats fiables dans un script, quels que soient les paramètres de l'utilisateur, définissez LC_ALL=C.

Gilles 'SO- arrête d'être méchant'
la source
0

Ensemble:

shopt -u nocaseglob

Depuis la page de manuel de bash:

>     nocaseglob
>         If  set,  bash matches filenames in a case-insensitive
>         fashion when performing pathname expansion (see Pathname
>          Expansion above).

Si vous définissez «globasciiranges», je ne sais pas ce qui arrivera aux caractères non-ascii comme utf-8

Udi
la source
0

echo [cC] * devrait faire ce que vous voulez, de la même façon [A-Za-z] *

Je suis ici parce que la globalisation sur mon système vient de cesser d' être sensible à la casse, donc les charges de mes scripts ne fonctionnent plus comme elles devraient :-(

user208007
la source
C'est l'opposé de ce que je vois. Mais vérifiez les autres réponses pour des suggestions.
rosuav