如果没有use utf8
Perl,会将您的字符串解释为单字节字符序列。如您所见,您的字符串中有四个字节:
$ perl -E 'say join ":", map { ord } split //, "鸡\n";'
233:184:161:10
前三个字节组成你的字符,最后一个是换行符。
调用print
将这四个字符发送到 STDOUT。然后,您的控制台会计算出如何显示这些字符。如果您的控制台设置为使用 UTF8,那么它将这三个字节解释为您的单个字符,这就是显示的内容。
如果我们在utf8
模块中添加,事情就不同了。在这种情况下,Perl 将您的字符串解释为两个字符。
$ perl -Mutf8 -E 'say join ":", map { ord } split //, "鸡\n";'
40481:10
默认情况下,Perl 的 IO 层假定它使用单字节字符。所以当你试图打印一个多字节字符时,Perl 认为有问题并给你一个警告。与以往一样,您可以通过包含use diagnostics
. 它会这样说:
(S utf8) Perl 遇到了一个宽字符 (>255),但它没有预料到它。此警告默认为 I/O(如打印)打开。消除此警告的最简单方法是将 :utf8 层添加到输出中,例如 binmode STDOUT, ':utf8'。另一种关闭警告的方法是添加 no warnings 'utf8'; 但这通常更接近作弊。通常,您应该使用编码显式标记文件句柄,请参阅 open 和 perlfunc/binmode。
正如其他人指出的那样,您需要告诉 Perl 接受多字节输出。有很多方法可以做到这一点(有关一些示例,请参阅Perl Unicode 教程)。最简单的方法之一是使用-CS
命令行标志 - 它告诉三个标准文件句柄(STDIN、STDOUT 和 STDERR)处理 UTF8。
$ perl -Mutf8 -e 'print "鸡\n";'
Wide character in print at -e line 1.
鸡
对比
$ perl -Mutf8 -CS -e 'print "鸡\n";'
鸡
Unicode 是一个大而复杂的领域。正如您所看到的,许多简单的程序似乎都在做正确的事情,但原因却是错误的。当您开始修复程序的一部分时,事情通常会变得更糟,直到您修复了所有程序。