Dans un shell : passer du texte en majuscules ou en minuscules

Je cherche un filtre qui passe en majuscules (ou en minuscules) toutes les lettres qu’il lit sur son entrée.

Sommaire

Avec tr

A priori, tr semble fait pour ça :

$ echo 'majuscules' | tr a-z A-Z
MAJUSCULES

On peut aussi utiliser les classes de caractères POSIX :

$ echo 'MAJUSCULES' | tr [:upper:] [:lower:]
majuscules

Malheureusement, le tr de GNU bute sur les signes diacritiques et les ligatures :

$ tr --version | head -n1
tr (GNU coreutils) 9.1
$ echo 'mæjùçcûlès' | tr a-z A-Z
MæJùçCûLèS
$ echo 'mæjùçcûlès' | tr [:lower:] [:upper:]
MæJùçCûLèS

Avec le tr installé sur macOS (provenant apparemment de FreeBSD, si j’en crois le manuel), cela fonctionne, à condition d’utiliser les classes POSIX :

$ echo 'mæjùçcûlès' | tr a-z A-Z
MæJùçCûLèS
$ echo 'mæjùçcûlès' | tr [:lower:] [:upper:]
MÆJÙÇCÛLÈS

Avec sed

La version GNU de sed (ci-après gsed) propose une extension à la commande s (voir la section 3.3 du manuel) :

On peut donc passer toute la ligne en majuscules avec la commande sed 's/.*/\U&/' :

$ echo 'mæjùçcûlès' | gsed 's/.*/\U&/'
MÆJÙÇCÛLÈS
$ echo 'MÆJÙÇCÛLÈS' | gsed 's/.*/\L&/'
mæjùçcûlès

Au passage, la chaîne \E annule l’effet de \U ou \L. On peut dès lors faire ce genre de choses :

$ echo 'MæJÙÇcÛLÈs' | sed 's/.*/\L& \E& \U&/'
mæjùçcûlès MæJÙÇcÛLÈs MÆJÙÇCÛLÈS

Un \u ou \l dans le champ de remplacement change seulement la casse du caractère qui le suit (j’utilise ici un _ plutôt qu’un / pour séparer les différents champs de la commande passée à sed) :

echo aBc | sed 's/a/\ua/ ; s/B/\lb/'
Abc

Le sed de macOS ne propose pas ces extension à la norme POSIX :

$ echo 'mæjùçcûlès' | sed 's/.*/\U&/'
Umæjùçcûlès

Avec awk

Les fonctions toupper() et tolower() de awk passent respectivement en capitales et en bas de casse la chaîne qu’on donne en argument.

Dans la version GNU de awk (gawk), cette fonction permet de changer la casse des caractères pourvus de diacritiques ainsi que des ligatures :

$ echo 'mæjùçcûlès' | gawk '{print toupper($0)}'
MÆJÙÇCÛLÈS
$ echo 'MÆJÙÇCÛLÈS' | gawk '{print tolower($0)}'
mæjùçcûlès

Attention : le awk installé par défaut sur Debian n’est pas celui de GNU mais mawk, avec lequel ça ne marche pas :

$ echo 'mæjùçcûlès' | mawk '{print toupper($0)}'
MæJùçCûLèS
$ echo 'MÆJÙÇCÛLÈS' | mawk '{print tolower($0)}'
mÆjÙÇcÛlÈs

Le awk de GNU s’installe facilement (sudo apt install gawk) ; une fois l’installation faite, la commande awk lancera gawk et non plus mawk.

Le awk installé par défaut sur macOS présente les mêmes limitations.

Conclusion

Si on est sur macOS :

Sur Linux :