Converter todo o texto de maiúsculas para minúsculas e vice-versa?

17

Minha pergunta é como posso converter todo o texto de maiúsculas para minúsculas e vice-versa? Isso é mudar os casos de todas as letras. Tem que ser feito com uma sedsubstituição de alguma forma.

MEZesUBI
fonte
4
trseria mais adequado do que sed.
choroba

Respostas:

20

Aqui está uma maneira direta de sed:

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

ou uma maneira mais curta com o GNU sed, trabalhando com qualquer caractere para o qual exista uma conversão em minúsculas <-> maiúsculas no seu código do idioma:

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

se você pode usar outras ferramentas, como:

perl (limitado a cartas ASCII):

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

perl (De forma geral):

$ echo 'αΒγ' | perl -Mopen=locale -pe 's/(\p{Ll})|(\p{Lu})/uc($1).lc($2)/ge'
ΑβΓ
cuonglm
fonte
3
O seu segundo assume um GNU sede um caso alternativo na entrada. Use em sed -re 's/([[:lower:]]?)([[:upper:]]?)/\U\1\L\2/g'vez disso (ainda específico do GNU). O primeiro converte apenas as 26 letras latinas ASCII, enquanto o segundo converte qualquer letra reconhecida como tal pela sua localidade. O trúnico faz sentido em locais ASCII. O perlúnico funciona para letras latinas ASCII.
Stéphane Chazelas
16

POSIXIAMENTE, isso não pode ser feito, sedexceto fornecendo o conjunto completo de letras que você deseja transliterar como o @cuonglm mostrou .

Poderia ser feito com isso tr, e tré para isso (transliterar):

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

No entanto, no Linux, há limitações. Das 3 trimplementações comumente encontradas em sistemas baseados em Linux:

  • com o GNU tr, que funciona apenas para conjuntos de caracteres de byte único. Por exemplo, em Stéphane Chazelaslocalidades UTF-8, isso fornece em sTéPHANE cHAZELASvez de sTÉPHANE cHAZELAS. Essa é uma limitação conhecida do GNU tr.
  • com a trpartir da caixa de ferramentas da herança, isso não funciona (você entende stéphane chazelas).
  • Esse não é o tipo de coisa que o busybox trfará.

No FreeBSD, porém, isso funciona bem. Você esperaria que ele funcionasse bem em sistemas Unix certificados também.


O bashshell possui um operador dedicado para isso:

in=AbCdE
out=${in~~}

Com zsh -o extendedglob:

out=${in//(#b)(([[:lower:]])|([[:upper:]]))/${(U)match[2]}${(L)match[3]}}
Stéphane Chazelas
fonte
Então, no mundo dos desktops, apenas o OSX faz isso? Por que não pode funcionar? São apenas as diferentes implementações, pois parece que há um deslocamento constante no valor hexadecimal entre a versão em minúscula do caractere acentuado e sua contraparte em maiúscula?
1
@ illuminÉ, não sei o que você quer dizer com mundo de desktop . AFAICS, o problema está no GNU, a maioria dos Unices possui "desktops". Além do ASCII e alguns conjuntos de caracteres iso8859, não sei que você pode generalizar a coisa de deslocamento hexadecimal, e isso não faria sentido com codificações como UTF-8. Por exemplo, em UTF-8, maiúsculas (e2 b4 a0) é (e1 83 80); ambos i(69) e ı(c4 b1) têm I(49) em maiúsculas (exceto nas localidades turcas onde ise torna İ). A razão pela qual ele não funciona com o GNU tré que o GNU trtrabalha com bytes e não com caracteres.
Stéphane Chazelas
Eu meio que quis dizer mainstream, mas não faz muito sentido, obrigado pelo aviso. Eu apenas olhei os caracteres acentuados franceses (e realmente apenas "é") e fiz suposições muito simplistas, esquecendo novamente que se trata de bytes. Mas a herança? Vou ler essa resposta novamente!
1
@ illuminÉ, para herança, é uma questão diferente, parece que suporta apenas apenas uma ocorrência de [:lower:]ou [:upper:](portanto, a primeira é ignorada). Mesmo em francês, œ -> Œestá c5 93 -> c5 92em UTF-8 e bd -> bcem iso8859-15.
Stéphane Chazelas
2

Embora isso tenha as mesmas limitações já mencionadas como a trsolução oferecida por Stéphane Chazelas, é outra maneira de fazê-lo:

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

RESULTADO

qwertyqwerty
QWERTYQWERTY

Eu despejo stderrpara /dev/nulllá porque ddtambém fornece estatísticas de todas as suas operações no 2descritor de arquivo. Isso pode ser útil dependendo do que você está fazendo, mas não foi para esta demonstração. Todas as outras coisas com as quais você pode fazer ddainda se aplicam, por exemplo:

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

RESULTADO:

QWERTY
QWERTY
mikeserv
fonte
Porém, ele não troca o caso (como em aBcnão é convertido em AbC).
Stéphane Chazelas
1
@ StéphaneChazelas - verdade, mas a menos que eu tenha entendido errado, essa não era a questão, era?
mikeserv
2

Se seu objetivo principal é converter um arquivo de classe baixa para classe alta, por que você não usa tre STDOUTpara converter seu arquivo:

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

Onde FILENAMEestá o seu arquivo original. Onde FILENAME2está o seu arquivo de saída convertido.

Rick
fonte
Não funcionou com caracteres acentuados, como épor exemplo (pelo menos no meu arquivo).
Sigur
1

usando awk:

awk '{print tolower($0)}' file.txt | tee file.txt
Hackaholic
fonte
Tem certeza de que isso vai funcionar? >file.txtcomeçaria truncando o arquivo
iruvar 22/09/16
2
Então você obviamente não tentou.
Stéphane Chazelas
0

ruby tem um método de string para isso, uso semelhante na linha de comando, como perl

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

Veja também Ruby-doc Encoding

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

Mantenha simples coisa simples. O filtro projetado para traduzir caracteres é tr.

echo 1ude1UDE | tr [:upper:][:lower:] [:lower:][:upper:]
Rogelio
fonte
1
Essa é uma versão quebrada (por causa das citações desaparecidas em torno dos operadores englobamento) de uma resposta já dada 2 anos antes
Stéphane Chazelas