![如何在 Bash 中转换 UTF-8 特殊字符?](https://linux22.com/image/1465836/%E5%A6%82%E4%BD%95%E5%9C%A8%20Bash%20%E4%B8%AD%E8%BD%AC%E6%8D%A2%20UTF-8%20%E7%89%B9%E6%AE%8A%E5%AD%97%E7%AC%A6%EF%BC%9F.png)
我正在编写一个脚本,用于从电子邮件中提取和保存 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($_);'
确保您仅传递编码文本部分而不是整个主题标题值。