Я пишу скрипт, который извлекает и сохраняет JPEG-вложения из писем и передает их в imagemagick. Однако я живу в Германии, и специальные символы в тексте/теме письма, такие как "ö", "ä", "ü" и "ß", встречаются довольно часто.
Я извлекаю тему с помощью formail:
SUBJECT=$(formail -zxSubject: <"$file")
и это приводит к:
- =?UTF-8?Q?Meine_G=c3=bcte?=
("Meine Güte") или даже хуже
- =?UTF-8?B?U2Now7ZuZSBHcsO8w59lIQ==?=
(«Прекрасная зелень!»).
Я пытаюсь использовать часть темы в качестве имени файла и текстовой аннотации imagemagick, но это, очевидно, не работает.
Как преобразовать этот текст UTF-8 в текст со специальными символами в bash?
Спасибо заранее! Маркус
решение1
Как преобразовать этот текст UTF-8 в текст со специальными символами в bash?
То, что у тебя есть, недовольно"Текст UTF-8". Вы на самом делехотетьпростой текст UTF-8 каквыход, поскольку именно его Linux использует для обозначения «специальных символов» повсюду.
Вместо этого ваш ввод — это MIME (Запрос на изменение 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?=
На основе значения кодировки закодированный текст декодируется либо как цитируемый-печатаемый (Q), либо как base64 (B).
Чтобы получить форму, удобную для чтения человеком, вам нужно передать часть закодированного текста заголовка темы в программу, которая его декодирует. Я думаю, что есть несколько отдельных команд для этого (uudecode), но я предпочитаю использовать однострочники Perl:
Для цитируемого-печатного:
perl -pe 'use MIME::QuotedPrint; $_=MIME::QuotedPrint::decode($_);'
и для base64:
perl -pe 'use MIME::Base64; $_=MIME::Base64::decode($_);'
Убедитесь, что вы передаете только закодированную часть текста, а не все значение заголовка темы.