Perl使用编码pragma破坏UTF字符串

Kar*_*lek 7 perl

我有Perl和编码编译指示的问题.

(我在输入,输出,perl脚本本身使用utf-8.我不想使用其他编码,从来没有.)

然而.当我写作

binmode(STDOUT, ':utf8');
use utf8;
$r = "\x{ed}";
print $r;
Run Code Online (Sandbox Code Playgroud)

我看到字符串" í "(这就是我想要的 - 以及什么是U + 00ED unicode char).但是当我添加像这样的"使用编码"pragma时

binmode(STDOUT, ':utf8');
use utf8;
use encoding 'utf8';
$r = "\x{ed}";
print $r;
Run Code Online (Sandbox Code Playgroud)

我所看到的只是一个盒子角色.为什么?

而且,当我添加Data :: Dumper并让Dumper打印出这样的新字符串时

binmode(STDOUT, ':utf8');
use utf8;
use encoding 'utf8';
$r = "\x{ed}";
use Data::Dumper;
print Dumper($r);
Run Code Online (Sandbox Code Playgroud)

我看到perl 将字符串更改"\x{fffd}".为什么?

Ano*_*mie 9

use encoding 'utf8'被打破.它不是将其解释\x{ed}为代码点U + 00ED,而是将其解释为单个字节237,然后尝试将其解释为UTF-8.当然哪个失败了,所以它最终用替换字符U + FFFD替换它,字面意思是" ".

只需坚持use utf8指定您的源是UTF-8,binmode或者使用open pragma来指定文件句柄的编码.

  • 据我所知,原因是"使用编码"的设计让人们可以编写"使用编码"euc-jp'; $ r ="\ xF1\xD1\xF1\xCC";`并将其解释为"正确".但这意味着你必须以相同的样式编写你的UTF-8字符串,如`$ r ="\ xC3\xAD";`.当与Perl对UTF-8的原生支持(例如`$ r ="\ x {200b}")相结合时会出现混淆,`代码为0x80-0xff的转义与代码为0x100及以上的转义的解释不同. (3认同)
  • 是的,Perl对8位语言环境的支持(`use encoding`,`use locale`)应该保留在一个很长的棒的另一端. (3认同)

hob*_*bbs 5

您的实际代码既不需要use encoding也不需要use utf8正常运行 - 它唯一依赖的是编码层STDOUT.

binmode(STDOUT, ":utf8");
print "\xed";
Run Code Online (Sandbox Code Playgroud)

是一个同样有效的完整程序,可以满足您的需求.

use utf8 只有在程序中的文字字符串中包含UTF-8时才应该使用 - 例如,如果您已经写过

my $r = "í";
Run Code Online (Sandbox Code Playgroud)

然后use utf8会导致该字符串被解释为单个字符U + 00ED而不是字节序列C3 AD.

use encoding永远不应该使用,特别是喜欢Unicode的人.如果你想要改变stdin/out的编码,你应该自己使用-C或者PERLUNICODEbinmode,如果你想要用编码层自动打开其他句柄你应该useopen.