¿Cómo convierto caracteres especiales UTF-8 en Bash?

¿Cómo convierto caracteres especiales UTF-8 en Bash?

Estoy escribiendo en un script que extrae y guarda archivos adjuntos JPEG de correos electrónicos y los pasa a imagemagick. Sin embargo, vivo en Alemania y los caracteres especiales en el texto/asunto del correo electrónico como "ö", "ä", "ü" y "ß" son bastante comunes.

Estoy extrayendo el asunto con formail:

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

y eso resulta en:

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

("Meine Güte") o incluso peor

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

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

Intento usar parte del tema como nombre de archivo y como anotación de texto imagemagick, lo que obviamente no funciona.

¿Cómo convierto este texto UTF-8 en texto con caracteres especiales en bash?

¡Gracias de antemano! Marcos

Respuesta1

¿Cómo convierto este texto UTF-8 en texto con caracteres especiales en bash?

lo que tienes no esbastante"Texto UTF-8". tu en realidaddeseartexto plano UTF-8 comoproducción, ya que es lo que Linux usa para los "caracteres especiales" en todas partes.

Su entrada, en cambio, es MIME (RFC 2047) codificado en UTF-8. La "Q" marca el modo Quoted-Printable y la "B" marca el modo Base64. Entre otros, PerlCodificar::MIME::Encabezadose puede utilizar 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 (ver perldoc perlrunexplicación):

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

Esto puede tomar cualquier 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!

Una versión en 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))

Respuesta2

El asunto del correo electrónico en sí es el encabezado y los encabezados deben contener sólo caracteres ASCII. Es por eso que se debe codificar el asunto UTF-8 (o cualquier otro conjunto de caracteres que no sea ASCII).

Esta forma de codificar caracteres no ASCII en ASCII se describe en RFC 1342.

Básicamente, el tema codificado tiene (como ya ha enumerado en sus ejemplos) el siguiente formato:

=?charset?encoding?encoded-text?=

Según el valor de codificación, el texto codificado se decodifica como imprimible entre comillas (Q) o como base64 (B).

Para obtener un formato legible por humanos, debe pasar la parte de texto codificado del valor del encabezado del asunto al programa que lo decodifica. Creo que hay algunos comandos independientes para hacer eso (uudecode), pero prefiero usar frases ingeniosas de Perl:

Para imprimible cotizado:

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

y para base64:

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

Asegúrese de pasar solo la parte del texto codificado y no el valor completo del encabezado del asunto.

información relacionada