Como converter arquivos txt UTF-8 para todos os maiúsculos no bash?

10

Eu tenho alguns arquivos .txt UTF-8 que gostaria de converter em maiúsculas. Se fosse apenas ASCII, eu poderia usar:

tr [:lower:] [:upper:]

Mas como estou trabalhando com diacríticos e coisas assim, não parece funcionar. Eu acho que pode funcionar se eu definir o local apropriado, mas eu preciso que este script seja portátil.

    
por VPeric 30.07.2013 / 18:55

3 respostas

14

Todos:

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

(não esqueça as aspas, caso contrário, não funcionará se houver um arquivo chamado : , l , ... ou r no diretório atual) ou:

awk '{print toupper($0)}'

ou:

dd conv=ucase

são destinados a converter caracteres em maiúsculas de acordo com as regras definidas na localidade atual. No entanto, mesmo onde as localidades usam UTF-8 como o conjunto de caracteres e definem claramente a conversão de minúsculas para maiúsculas, pelo menos, GNU dd , GNU tr e mawk (o padrão awk no Ubuntu, por exemplo) don siga-os. Além disso, não há padrão maneira de especificar localidades diferentes de C ou POSIX , portanto, se você deseja converter arquivos UTF-8 para portáteis em maiúsculas, independentemente da localidade atual, você está sem sorte com o ferramental padrão.

Com frequência, para portabilidade, sua melhor aposta pode ser perl:

$ echo lľsšcčtťzž | PERLIO=:utf8 perl -pe '$_=uc'
LĽSŠCČTŤZŽ

Agora, você precisa tomar cuidado para que nem todos concordem com a versão maiúscula de um caractere específico.

Por exemplo, nas localidades turcas, a maiúscula i não é I , mas İ ( <U0130> ). Aqui com o toolchest heirloom tr em vez de GNU tr:

$ echo ií | LC_ALL=C.UTF-8 tr '[:lower:]' '[:upper:]'
IÍ
$ echo ií | LC_ALL=tr_TR.UTF-8 tr '[:lower:]' '[:upper:]'
İÍ

No meu sistema, a conversão de perl para superior está definida em /usr/share/perl/5.14/unicore/To/Upper.pl , e acho que ela se comporta de maneira diferente em alguns caracteres do GNU libc toupper() no C.UTF8 locale, por exemplo, perl sendo mais preciso. Por exemplo, perl converte corretamente / para Ɀ , o GNU libc (2.17) não.

    
por 30.07.2013 / 21:11
3

Acho que você pode fazer isso com awk e sua função toupper .

Por exemplo

Não funciona com o GNU tr :

$ echo lľsšcčtťzž | tr '[:lower:]' '[:upper:]'
LľSšCčTťZž

Funciona com o GNU awk :

$ echo lľsšcčtťzž | awk '{ print toupper($0) }'
LĽSŠCČTŤZŽ
    
por 30.07.2013 / 19:33
1

Isso funciona com tr do OS X, mas não com o GNU tr :

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

Isso funciona com gawk , mas não com mawk ou nawk (que é /usr/bin/awk no OS X):

awk '{print toupper($0)}'

Outra opção é usar o GNU sed :

sed 's/./\u&/g'

No Bash 4.0 e posterior, você também pode usar a expansão do parâmetro ^^ :

while IFS= read -r l;do printf %s\n "${l^^}";done
    
por 07.05.2016 / 02:22