【问题标题】:Printing a string containing utf-8 byte sequences on perl在 perl 上打印包含 utf-8 字节序列的字符串
【发布时间】:2019-09-21 11:23:23
【问题描述】:

我是 perl 新手,我正在尝试从 mork 文件(来自 Thunderbird)中打印出文件夹名称。

发件人:https://github.com/KevinGoodsell/mork-converter/blob/master/doc/mork-format.txt

第二种特殊字符序列是美元符号 后跟两个十六进制数字,它们给出的值 替换字节。这通常用于不可打印的字节 作为 ASCII 字符,尤其是在 UTF-16 文本中。例如,一个字符串 带有 Unicode 雪人字符 (U+2603):

☃雪人☃

可以通过这种方式在别名中表示为 UTF-16 文本:

从我看到的所有 Thunderbird 文件中,它实际上是用 UTF-8(2 到 4 个字节)编码的。

以下字符需要在字符串中转义(使用\)才能按字面意思使用:$、) 和 \

例如:aaa\$AA$C3$B1b$E2$98$BA$C3$AD\\x08 应该打印 aaa$AAñb☺í\x08

$C3$B1 是ñ; $E2$98$BA 是 ☺; $C3$AD是í

我尝试使用正则表达式将未转义的 $ 替换为 \x

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

在 perl 中它只打印文字字符串。

我的解决方法是将它输入 bash 的 printf 并且它成功了...除非字符串中有文字“\x”

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

我咨询过的问题:

Convert UTF-8 character sequence to real UTF-8 bytes 但似乎它自己解释每个字节,而不是分组。

In Perl, how can I convert an array of bytes to a Unicode string? 我不知道如何将此解决方案应用于我的用例。

有没有办法在 perl 中实现这一点?

【问题讨论】:

标签: linux perl unicode utf-8 mork


【解决方案1】:

以下替换似乎适用于您的输入:

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

捕获\$ 或\\,如果匹配,则将它们替换为$ 或\。否则,捕获$..并转换为对应的字节。

如果您想在 Perl 中处理结果,请不要忘记将其从 UTF-8 解码。

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

【讨论】:

  • choroba 使用/r 导致返回修改后的字符串,而不是就地修改字符串。只需删除 r 即可继续原地工作。
  • 在不了解规范的情况下,\\(\W) 可能比\\([\$\\]) 更好。 s{\\(\W)|\\(\w))|\$([0-9a-fA-F]{2})|\$}{ defined($1) ? $1 : defined($2) ? die("Unsupported \\$2 escape") : defined($3) ? chr(hex($3)) : die('Invalid "$" sequence') }ges
  • 谢谢,成功了!如果我只想打印结果,是否需要使用 Encode::decode? (将其捕获到 bash 变量中)。从我使用它的实验来看,它抱怨打印一个宽字符,除非我设置binmode (STDOUT, ":utf8");
  • @Bangaio 是的,您需要将所有输出编码到包含非 ascii 字符的终端。您可以通过将其编码(如果您确定它已经在您的终端期望的编码中并且您不想先执行任何字符串操作)、使用 Encode::encode 显式编码解码的字符串或设置像您提到的编码层,因此所有字符串在发送到该句柄时都会被编码(但您应该使用:encoding(UTF-8),而不是:utf8)。最后一个选项的唯一问题是它是一个全局效应,其他事情可能不会预料到。
猜你喜欢
  • 2019-04-09
  • 1970-01-01
  • 2018-06-04
  • 1970-01-01
  • 2013-03-09
  • 2011-08-16
  • 2012-01-20
  • 1970-01-01
  • 2020-05-29
相关资源
最近更新 更多