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

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

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

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!").

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

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

Desde já, obrigado! Marcus

Responder1

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

O que você tem não ébastante"Texto UTF-8". Você realmentequerertexto simples UTF-8 comosaída, pois é o que o Linux usa para "caracteres especiais" em todos os lugares.

Sua entrada, em vez disso, é MIME (RFC 2047) codificado em UTF-8. O "Q" marca o modo Quoted-Printable e o "B" marca o modo Base64. Entre outros, PerlCodificar::MIME::Cabeçalhopode 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 perlrunpara explicação):

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

Isso pode assumir 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!

Uma versão em Python 3:

#!/usr/bin/env python3
import email.header, sys

words = email.header.decode_header(sys.stdin.read())
words = [s.decode(c or "utf-8") for (s, c) in words]
print("".join(words))

Responder2

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

Esta forma de codificar caracteres não ASCII para ASCII é descrita na RFC 1342.

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

=?charset?encoding?encoded-text?=

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

Para obter um formato legível por humanos, você precisa passar a parte do texto codificado do valor do cabeçalho do assunto para o programa que o decodifica. Acredito que existam alguns comandos independentes para fazer isso (uudecode), mas prefiro usar one-liners Perl:

Para impressão cotada:

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 inteiro do cabeçalho do assunto.

informação relacionada