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


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

Eu estou extraindo o assunto com formail:

    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 anotação de texto imagemagick, o que obviamente não funciona.

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

Desde já, obrigado! Markus


4


origem


Espaços entre palavras e pontuação também estão ausentes :( - Markus


Respostas:


Como faço para converter este texto UTF-8 para texto com caracteres especiais no 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) codificado UTF-8. O "Q" marca o modo Quoted-Printable e "B" marca o modo Base64. Entre outros, Perl Encode :: MIME :: Header pode ser usado para decodificar ambos:

#!/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!

6



O one-liner não funcionou para mim. (veja @blami). Mas o código pl funcionou bem. Quando usei o último script, a parte Base64 não foi codificada. Nem mesmo quando tentei apenas essa parte. Sua explicação me ajudou também. - Markus


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.

Essa 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-liners Perl:

Para citado para impressã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.


5



Obrigado pelo seu comentário! Eu aprendi muito com sua explicação detalhada. No entanto, eu não poderia obter os one-liners para executar corretamente (em putty no raspberry pi). Mas tenho certeza que isso é apenas por causa das minhas habilidades de linux pobres. Eu usei echo "=? UT ...:" | perl ... e o resultado foi "=? UTF-8? Q? Meine_Güte?". Apenas o "ü" foi traduzido. O script fornecido pelo @grawity produziu bons resultados. - Markus