Convertire tutto il testo da maiuscolo a minuscolo e viceversa?


17

La mia domanda è: come posso convertire tutto il testo da maiuscolo a minuscolo e viceversa? Ciò significa cambiare i casi di tutte le lettere. Deve essere fatto in sedqualche modo con una sostituzione.


4
trsarebbe più adatto di sed.
Choroba,

Risposte:


20

Ecco un modo semplice in sed:

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

o un modo più breve con GNU sed, lavorando con qualsiasi carattere per il quale esiste una conversione in minuscolo <-> maiuscolo nella tua locale:

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

se puoi usare altri strumenti, come:

perl (limitato alle lettere ASCII):

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

perl (più generalmente):

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

3
Il secondo presuppone una GNU sede un caso alternativo nell'input. Usa sed -re 's/([[:lower:]]?)([[:upper:]]?)/\U\1\L\2/g'invece (ancora specifico per GNU). Il primo converte solo le 26 lettere latine ASCII, mentre il secondo converte qualsiasi lettera riconosciuta come tale dalle impostazioni internazionali. Quello trha senso solo in locali ASCII. Quello perlfunziona solo per lettere latine ASCII.
Stéphane Chazelas,

16

POSIX, ciò non può essere fatto sedse non fornendo l'insieme completo di lettere che si desidera traslitterare come ha mostrato @cuonglm .

Si potrebbe fare con trperò, ed è quello che trserve per (traslitterare):

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

Tuttavia, su Linux ha dei limiti. Delle 3 trimplementazioni che si trovano comunemente sui sistemi basati su Linux:

  • con GNU tr, che funziona solo per set di caratteri a byte singolo. Ad esempio, su Stéphane Chazelasnelle lingue UTF-8, che fornisce sTéPHANE cHAZELASinvece di sTÉPHANE cHAZELAS. Questa è una limitazione nota di GNU tr.
  • con trdal cimelio di cimelio, che non funziona (ottieni stéphane chazelas).
  • Non è questo il tipo di cose che farebox tr.

Su FreeBSD però funziona bene. Ti aspetteresti che funzioni anche su sistemi Unix certificati.


La bashshell ha un operatore dedicato per questo:

in=AbCdE
out=${in~~}

Con zsh -o extendedglob:

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

Quindi nel mondo desktop solo OSX lo fa? Perché non funziona? Sono solo le diverse implementazioni in quanto sembra che ci sia un offset costante nel valore esadecimale tra la versione minuscola del carattere accentato e la sua controparte maiuscola?

1
@ illuminÉ, non so cosa intendi per mondo desktop . AFAICS, il problema è con GNU, la maggior parte degli Unices ha "desktop". A parte ASCII e alcuni set di caratteri iso8859, non sono consapevole del fatto che puoi generalizzare la cosa di offset esadecimale, e questo non avrebbe senso con codifiche come UTF-8. Ad esempio in UTF-8, maiuscolo (e2 b4 a0) è (e1 83 80); entrambi i(69) e ı(c4 b1) hanno I(49) in maiuscolo (tranne che nei locali turchi dove idiventa İ). Il motivo per cui non funziona con GNU trè che GNU trfunziona con byte e non con caratteri.
Stéphane Chazelas,

In un certo senso volevo dire mainstream ma non ha molto senso, quindi grazie per il testa a testa. Ho appena guardato i caratteri accentati francesi (e davvero solo "é") e fatto ipotesi semplicistiche, dimenticando ancora che si tratta di byte. Ma quello cimelio? Vado a leggere di nuovo quella risposta!

1
@ illuminare, per cimelio, è una questione diversa, a quanto pare supporta solo una sola occorrenza di [:lower:]o [:upper:](in modo che il primo viene ignorato). Anche in francese, œ -> Œè c5 93 -> c5 92in UTF-8 e bd -> bcin iso8859-15.
Stéphane Chazelas,

2

Sebbene questo abbia gli stessi limiti già menzionati come la trsoluzione offerta da Stéphane Chazelas, è un altro modo per farlo:

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

PRODUZIONE

qwertyqwerty
QWERTYQWERTY

I discarica stderrin /dev/nulllà perché ddfornisce anche le statistiche di tutte le sue operazioni sul 2descrittore di file. Questo può essere utile a seconda di ciò che stai facendo, ma non era per questa dimostrazione. Tutte le altre cose che puoi fare con ddsi applicano ancora, ad esempio:

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

PRODUZIONE:

QWERTY
QWERTY

Tuttavia non sostituisce il caso (poiché in aBcnon viene convertito in AbC).
Stéphane Chazelas,

1
@ StéphaneChazelas - vero, ma se non ho frainteso, non era questa la domanda, vero?
Mikeserv,

2

Se il tuo obiettivo principale è convertire un file da minuscole a maiuscole, perché non lo usi tre STDOUTper convertire il tuo file:

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

Dov'è il FILENAMEtuo file originale. Dov'è il FILENAME2tuo file di output convertito.


Non ha funzionato con caratteri accentati, come éad esempio (almeno nel mio file).
Sigur,


0

ruby ha un metodo stringa per questo, un uso simile dalla riga di comando come perl

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

Vedi anche la codifica ruby-doc

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.