使用'使用utf8' 给我“宽印字”

如果我运行下面的Perl程序:

perl -e 'use utf8; print "鸡\n";' 

我得到这个警告:

 Wide character in print at -e line 1. 

如果我运行这个Perl程序:

 perl -e 'print "鸡\n";' 

我没有得到警告。

我认为use utf8需要在Perl脚本中使用UTF-8字符。 为什么这不起作用,我该如何解决? 我正在使用Perl 5.16.2。 我有同样的问题,如果这是在一个文件中,而不是在命令行上的单线程。

如果不use utf8 Perl会将您的string解释为单字节字符序列。 在你的string中有四个字节,你可以看到:

 $ perl -E 'say join ":", map { ord } split //, "鸡\n";' 233:184:161:10 

前三个字节组成你的angular色,最后一个是换行符。

print电话将这四个字符发送到STDOUT。 然后,您的控制台了解如何显示这些字符。 如果您的控制台设置为使用UTF8,那么它将把这三个字节解释为单个字符,这就是显示的内容。

如果我们joinutf8模块,情况就不一样了。 在这种情况下,Perl会将您的string解释为两个字符。

 $ 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'。 另一种closures警告的方法是不添加警告'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.鸡 

VS

 $ perl -Mutf8 -CS -e 'print "鸡\n";'鸡 

Unicode是一个大而复杂的领域。 正如你所看到的,许多简单的程序似乎做正确的事情,但出于错误的原因。 当你开始修复程序的一部分,事情往往会变得更糟,直到你修好了所有的程序。

全部use utf8; 这是告诉Perl的源代码使用UTF-8编码。 你需要告诉Perl如何编码你的文本:

 use open ':std', ':encoding(UTF-8)'; 

将所有标准输出编码为UTF-8:

 binmode STDOUT, ":utf8"; 

你可以通过使用CPAN模块utf8::all来接近“只要做到utf8”。

 perl -Mutf8::all -e 'print "鸡\n";' 

print接收到不能打印的东西时(当没有:encoding层被提供时字符大于255),它假定你打算使用UTF-8对它进行编码。 这是在警告了这个问题之后。

你可以使用这个,

 perl -CS filename. 

它也将终止那个错误。

用西class牙语,你可以在旁边开始使用时发现这个错误:

 use utf8; 

您的编辑器编码是在不同的编码。 所以你在编辑器上看到的不是Perl所做的。 要解决该错误,只需将编辑器编码更改为Unicode / UTF-8