Bash で UTF-8 特殊文字を変換するにはどうすればよいですか?

Bash で UTF-8 特殊文字を変換するにはどうすればよいですか?

私は電子メールから JPEG 添付ファイルを抽出して保存し、それを imagemagick に渡すスクリプトを作成しています。しかし、私はドイツに住んでおり、電子メールのテキスト/件名に「ö」、「ä」、「ü」、「ß」などの特殊文字がよく使われています。

formailで件名を抽出しています:

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

その結果は次のようになります。

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

(「私の良いところ」)あるいはさらに悪い

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

(「Schöne Grüße!」)。

件名の一部をファイル名や imagemagick テキスト注釈として使用しようとしましたが、明らかに機能しません。

この UTF-8 テキストを bash で特殊文字を含むテキストに変換するにはどうすればよいですか?

よろしくお願いします! マルクス

答え1

この UTF-8 テキストを bash で特殊文字を含むテキストに変換するにはどうすればよいですか?

あなたが持っているものはとても「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 文字セット) でエンコードする必要があります。

非 ASCII 文字を ASCII にエンコードするこの方法は、RFC 1342 で説明されています。

基本的に、エンコードされた件名は(すでに例に挙げたとおり)次の形式になります。

=?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($_);'

件名ヘッダー値全体ではなく、エンコードされたテキスト部分のみを渡すようにしてください。

関連情報