Печать строки, содержащей последовательности байтов utf-8, на perl - PullRequest
1 голос
/ 03 мая 2019

Я новичок в Perl и пытаюсь распечатать папку Name из файлов mork (из Thunderbird).

From: https://github.com/KevinGoodsell/mork-converter/blob/master/doc/mork-format.txt

Второйтип последовательности специальных символов - знак доллара, за которым следуют две шестнадцатеричные цифры, которые дают значение байта замены.Это часто используется для байтов, которые нельзя распечатать как символы ASCII, особенно в тексте UTF-16.Например, строка с символом снеговика Unicode (U + 2603):

nowsnowman☃

может быть представлена ​​в виде текста UTF-16 в псевдониме следующим образом:

<(83 = $ 03 $ 26s $ 00n $ 00o $ 00w $ 00m $ 00a $ 00n $ 00 $ 03 $ 26)>

Из всех файлов Thunderbird, которые я видел, он фактически закодирован в UTF-8(От 2 до 4 байтов).

Следующие символы должны быть экранированы (\) внутри строки, чтобы использоваться буквально: $, ) и \

Пример: aaa\$AA$C3$B1b$E2$98$BA$C3$AD\\x08 должен напечатать aaa$AAñb☺í\x08

$C3$B1 is ñ;$E2$98$BA равно ;$C3$AD is í

Я пытался использовать регулярное выражение для замены неэкранированного $ на \x

my $unescaped = qr/(?<!\\)(?:(\\\\)*)/;
$folder =~ s/$unescaped\$/\\x/g;
$folder =~ s/\\([\\$)])/$1/g;   # unescape "\ $ ("

В perl он просто печатает буквенную строку.

Мой обходной путь - подать его в printf bash, и он преуспевает ... если только в строке нет буквального символа "\ x"

$ folder=$(printf "$(mork.pl 8777646a.msf)")
$ echo "$folder"
  aaa$AAñb☺í

Вопросы, с которыми я консультировался:

КонвертироватьПоследовательность символов UTF-8 в реальные байты UTF-8 Но, похоже, он интерпретирует каждый байт сам по себе, а не в группах.

В Perl, как я могу преобразовать массив байтов вСтрока Unicode? Я не знаю, как применить это решение в моем случае использования.

Есть ли способ добиться этого в perl?

1 Ответ

1 голос
/ 03 мая 2019

Кажется, что для вашего ввода сработает следующая подстановка:

s/\\([\$\\])|\$(..)/$2 ? chr hex $2 : $1/ge;

Capture \$ или \\, если они совпадают, замените их на $ или \. В противном случае перехватите $.. и преобразуйте в соответствующий байт.

Если вы хотите работать с результатом в Perl, не забудьте декодировать его из UTF-8.

$chars = decode('UTF-8', $bytes);
...