如何在 Bash 中轉換 UTF-8 特殊字元?

如何在 Bash 中轉換 UTF-8 特殊字元?

我正在編寫一個腳本,從電子郵件中提取並保存 JPEG 附件並將它們傳遞給 imagemagick。然而,我住在德國,電子郵件文字/主題中的特殊字元“ö”、“ä”、“ü”和“ß”非常常見。

我正在用 formail 提取主題:

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

結果是:

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

(“Meine Güte”)或更糟

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

(“Schöne Grüße!”)。

我嘗試使用主題的一部分作為文件名和 imagemagick 文字註釋,這顯然不起作用。

如何在 bash 中將此 UTF-8 文字轉換為帶有特殊字元的文字?

先致謝!馬庫斯

答案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);
}

Oneliner(參見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?=

根據編碼值,編碼文字被解碼為可引用列印 (Q) 或 base64 (B)。

為了獲得人類可讀的形式,您需要將主題標頭值的編碼文字部分傳遞給對其進行解碼的程式。我相信有一些獨立的命令可以做到這一點(uudecode),但我更喜歡使用 Perl 單行命令:

對於引用可列印:

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

對於 Base64:

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

確保僅傳遞編碼文字部分而不是整個主題標頭值。

相關內容