Convertir tout le texte des majuscules en minuscules et vice versa?


17

Ma question est de savoir comment convertir tout le texte des majuscules en minuscules et vice versa? C'est changer les cas de toutes les lettres. Cela doit être fait avec un sedremplacement en quelque sorte.


4
trserait plus approprié que sed.
choroba

Réponses:


20

Voici une façon simple de sed:

$ echo qWeRtY | sed -e 'y/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/'
QwErTy

ou d'une manière plus courte avec GNU sed, en travaillant avec n'importe quel caractère pour lequel une conversion en minuscules <-> majuscules existe dans votre environnement local:

$ echo qWeRtY | sed -E 's/([[:lower:]])|([[:upper:]])/\U\1\L\2/g'
QwErTy

si vous pouvez utiliser un autre outil, comme:

perl (limité aux lettres ASCII):

$ echo qWeRtY | perl -pe 'y/[a-z][A-Z]/[A-Z][a-z]/'
QwErTy

perl (plus généralement):

$ echo 'αΒγ' | perl -Mopen=locale -pe 's/(\p{Ll})|(\p{Lu})/uc($1).lc($2)/ge'
ΑβΓ

3
Votre deuxième suppose un GNU sedet un cas alternatif dans l'entrée. Utilisez à la sed -re 's/([[:lower:]]?)([[:upper:]]?)/\U\1\L\2/g'place (toujours spécifique à GNU). La première convertit uniquement les 26 lettres latines ASCII, tandis que la seconde convertit toute lettre reconnue comme telle par votre environnement local. L' trun n'a de sens que dans les paramètres régionaux ASCII. Celui perlne fonctionne que pour les lettres latines ASCII.
Stéphane Chazelas

16

POSIX, cela ne peut pas être fait sedsauf en fournissant l'ensemble complet de lettres que vous souhaitez translittérer comme l' a montré @cuonglm .

Cela pourrait être fait avec tr, et c'est à cela que trsert (translittération):

tr '[:lower:][:upper:]' '[:upper:][:lower:]'

Cependant, sous Linux, il a des limites. Sur les 3 trimplémentations couramment trouvées sur les systèmes Linux:

  • avec GNU tr, qui ne fonctionne que pour les jeux de caractères à un octet. Par exemple, Stéphane Chazelasdans les locales UTF-8, cela donne à la sTéPHANE cHAZELASplace de sTÉPHANE cHAZELAS. C'est une limitation connue de GNU tr.
  • avec trde l'héritage toolchest, cela ne fonctionne pas (vous obtenez stéphane chazelas).
  • Ce n'est pas le genre de chose que busybox trfera.

Sur FreeBSD, cela fonctionne bien. Vous vous attendriez à ce que cela fonctionne également dans les systèmes Unix certifiés.


Le bashshell a un opérateur dédié pour cela:

in=AbCdE
out=${in~~}

Avec zsh -o extendedglob:

out=${in//(#b)(([[:lower:]])|([[:upper:]]))/${(U)match[2]}${(L)match[3]}}

Donc, dans le monde du bureau, seul OSX le fait? Pourquoi ça ne marche pas? S'agit-il simplement des différentes implémentations, car il semble qu'il y ait un décalage constant dans la valeur hexadécimale entre la version minuscule du caractère accentué et son homologue majuscule?

1
@ illuminÉ, vous ne savez pas ce que vous entendez par monde de bureau . AFAICS, le problème est avec GNU, la plupart des Unices ont des "bureaux". Mis à part ASCII et certains jeux de caractères iso8859, je ne suis pas conscient que vous pouvez généraliser le décalage hexadécimal, et cela n'aurait aucun sens avec des encodages comme UTF-8. Par exemple, en UTF-8, majuscule (e2 b4 a0) est (e1 83 80); deux i(69) et ı(c4 b1) ont I(49) en majuscules (sauf dans des endroits où la Turquie idevient İ). La raison pour laquelle cela ne fonctionne pas avec GNU trest que GNU trfonctionne avec des octets et non avec des caractères.
Stéphane Chazelas

Je voulais dire du courant dominant, mais cela n'a pas vraiment de sens, alors merci pour la tête. Je viens de regarder les caractères accentués français (et vraiment juste "é") et j'ai fait des hypothèses très simplistes, oubliant encore qu'il s'agit d'octets. Mais l'héritage? Je vais relire cette réponse!

1
@ illuminÉ, pour heirloom, c'est un problème différent, il semble qu'il ne supporte qu'une seule occurrence de [:lower:]or [:upper:](donc la première est ignorée). Même en français, œ -> Œest c5 93 -> c5 92en UTF-8 et bd -> bcen iso8859-15.
Stéphane Chazelas

2

Bien que cela ait les mêmes limites déjà mentionnées que la trsolution proposée par Stéphane Chazelas, c'est une autre façon de le faire:

{   echo QWERTYqwerty | dd conv=lcase
    echo QWERTYqwerty | dd conv=ucase 
} 2>/dev/null

PRODUCTION

qwertyqwerty
QWERTYQWERTY

Je larguer stderren /dev/nulllà parce que ddfournit également des statistiques de toutes ses opérations sur le 2descripteur de fichier. Cela peut être utile selon ce que vous faites, mais ce n'était pas le cas pour cette démonstration. Toutes les autres choses que vous pouvez faire dds'appliquent toujours, par exemple:

echo QWERTYqwerty | dd bs=1 cbs=6 conv=unblock,ucase 2>/dev/null

PRODUCTION:

QWERTY
QWERTY

Cependant, il n'échange pas le cas (car in aBcn'est pas converti en AbC).
Stéphane Chazelas

1
@ StéphaneChazelas - c'est vrai, mais à moins que j'aie mal compris, ce n'était pas la question, n'est-ce pas?
mikeserv

2

Si votre objectif principal est de convertir un fichier de classe inférieure en classe supérieure, pourquoi ne l'utilisez-vous pas tret STDOUTpour convertir votre fichier:

$cat FILENAME | tr a-z A-Z > FILENAME2

Où se FILENAMEtrouve votre fichier d'origine. Où se FILENAME2trouve votre fichier de sortie converti.


Cela ne fonctionnait pas avec les caractères accentués, comme épar exemple (au moins dans mon fichier).
Sigur

1

utilisant awk:

awk '{print tolower($0)}' file.txt | tee file.txt

tu es sûr que ça va marcher? >file.txtcommencerait par tronquer le fichier
iruvar

2
Alors vous ne l'avez évidemment pas essayé.
Stéphane Chazelas

0

ruby a une méthode de chaîne pour cela, une utilisation similaire à partir de la ligne de commande comme perl

$ echo 'qWeRtY' | ruby -pe '$_.swapcase!'
QwErTy

Voir aussi Ruby-doc Encoding

$ ruby -e 'puts Encoding.default_external'
UTF-8
$ echo 'αΒγ'  | ruby -pe '$_.swapcase!'
ΑβΓ

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.