如何在 Bash 中转换 UTF-8 特殊字符?

如何在 Bash 中转换 UTF-8 特殊字符?

我正在编写一个脚本,用于从电子邮件中提取和保存 JPEG 附件并将其传递给 imagemagick。但是,我住在德国,电子邮件文本/主题中的特殊字符(如“ö”、“ä”、“ü”和“ß”)非常常见。

我正在使用 formail 提取主题:

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

结果是:

  • =?UTF-8?Q?我的G=c3=bcte?=

(“Meine Güte”)或者更糟

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

(“美丽的问候!”)。

我尝试将主题的一部分用作文件名和 imagemagick 文本注释,但这显然不起作用。

如何在 bash 中将此 UTF-8 文本转换为带有特殊字符的文本?

提前致谢!Markus

答案1

如何在 bash 中将此 UTF-8 文本转换为带有特殊字符的文本?

你所拥有的不是相当“UTF-8 文本”。你实际上纯 UTF-8 文本作为输出,因为 Linux 到处都使用它来表示“特殊字符”。

您的输入是 MIME (RFC 2047) 编码的 UTF-8。“Q”表示 Quoted-Printable 模式,“B”表示 Base64 模式。其中,Perl 的编码::MIME::标头可用于解码:

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

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

一句话(请参阅perldoc perlrun解释):

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

这可以接受任何格式作为输入:

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

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))

答案2

电子邮件主题本身就是标题,并且标题必须仅包含 ASCII 字符。这就是为什么必须对 UTF-8(或任何其他非 ASCII 字符集)主题进行编码的原因。

RFC 1342 中描述了将非 ASCII 字符编码为 ASCII 的方式。

基本上,编码主题具有(正如您在示例中已经列出的)以下格式:

=?charset?encoding?encoded-text?=

根据编码值,编码文本被解码为 quoted-printable (Q) 或 base64 (B)。

要获得人类可读的格式,您需要将主题标头值的编码文本部分传递给对其进行解码的程序。我相信有一些独立命令可以做到这一点(uudecode),但我更喜欢使用 Perl 单行命令:

对于 quoted-printable:

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

对于 base64:

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

确保您仅传递编码文本部分而不是整个主题标题值。

相关内容