Como faço para converter caracteres especiais UTF-8 no Bash?

5

Estou escrevendo um script que extrai e salva anexos de arquivos JPEG de e-mails e os transmite para o imagemagick. No entanto, estou morando na Alemanha e os caracteres especiais no texto / assunto do e-mail como "ö", "ä", "ü" e "ß" são bastante comuns.

Estou extraindo o assunto com o formato:

    SUBJECT=$(formail -zxSubject: <"$file")

e isso resulta em:

  • =? UTF-8? Q? Meine_G = c3 = bcte? =

("Meine Güte") ou pior ainda

  • =? UTF-8? B? U2Now7ZuZSBHcsO8w59lIQ ==? =

("Schöne Grüße!").

Eu tento usar parte do assunto como um nome de arquivo e como uma anotação de texto imagemagick, o que obviamente não funciona.

Como faço para converter este texto UTF-8 em texto com caracteres especiais no bash?

Obrigado antecipadamente! Markus

    
por Markus 13.09.2015 / 01:16

2 respostas

6

How do I convert this UTF-8 text to text with special characters in bash?

O que você tem não é bastante "texto UTF-8". Você realmente quer texto simples UTF-8 como saída , como é o que o Linux usa para "caracteres especiais" em todos os lugares.

Sua entrada, em vez disso, é MIME ( RFC 2047 ) codificada como UTF-8. O "Q" marca o modo Quoted-Printable e "B" marca o modo Base64. Entre outros, o Encode :: MIME :: Header do Perl pode ser usado para decodificar os dois:

#!/usr/bin/env perl
use open qw(:std :utf8);
use Encode qw(decode);

while (my $line = <STDIN>) {
        print decode("MIME-Header", $line);
}

Oneliner (veja perldoc perlrun para explicação):

perl -CS -MEncode -ne 'print decode("MIME-Header", $_)'

Isso pode levar qualquer formato como entrada:

$ echo "Subject: =?UTF-8?Q?Meine_G=c3=bcte?=, \
                 =?UTF-8?B?U2Now7ZuZSBHcsO8w59lIQ==?=" | perl ./decode.pl
Subject: Meine Güte, Schöne Grüße!
    
por 13.09.2015 / 02:10
6

O assunto do e-mail é cabeçalho e os cabeçalhos devem conter apenas caracteres ASCII. É por isso que o assunto UTF-8 (ou qualquer outro não-ASCII charset) deve ser codificado.

Esta maneira de codificar caracteres não-ASCII em ASCII é descrita na RFC 1342.

Basicamente, o sujeito codificado tem (como você já listou em seus exemplos) o seguinte formato:

=?charset?encoding?encoded-text?=

Com base no valor de codificação, o texto codificado é decodificado como citado imprimível (Q) ou como base64 (B).

Para obter um formato legível, você precisa passar uma porção de texto codificado do valor do cabeçalho do assunto para o programa que o decodifica. Eu acredito que existem alguns comandos independentes para fazer isso (uudecode), mas eu prefiro usar o one-liner Perl:

Para impressão com cotação:

perl -pe 'use MIME::QuotedPrint; $_=MIME::QuotedPrint::decode($_);'

e para base64:

perl -pe 'use MIME::Base64; $_=MIME::Base64::decode($_);'

Certifique-se de passar apenas a parte do texto codificado e não o valor do cabeçalho do assunto inteiro.

    
por 13.09.2015 / 02:10