使用“ use utf8;” 给我“打印中的宽字符”


86

如果我运行以下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。如果这是在文件中而不是在命令行中使用一个衬板,我也会遇到同样的问题。


3
“为什么这不起作用?” 它确实可以工作,但是根据我对Unicode的经验,有很多看起来很糟糕的程序似乎在工作。当您修复一件事时,使代码的错误几率降低了,结果似乎差很多。只有修复了最后一部分,所有内容才再次看起来不错。
霍布斯

Answers:


110

不使用use utf8Perl时,会将您的字符串解释为单字节字符序列。从此可以看到,字符串中有四个字节:

$ 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。它会这样说:

(Sutf8)Perl没想到会遇到一个宽字符(> 255)。对于I / O(如打印),默认情况下此警告处于打开状态。消除此警告的最简单方法是将:utf8层添加到输出中,例如binmode STDOUT,':utf8'。关闭警告的另一种方法是不添加警告'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是一个庞大而复杂的领域。如您所见,许多简单的程序似乎在做正确的事情,但是出于错误的原因。当您开始修复程序的一部分时,往往会变得更糟,直到您修复了所有程序。


-Mutf8如果不在一个内胆perl中怎么拼写?
雷杨

@LeiYang:use utf8;
Dave Cross

80

所有use utf8;做只是告诉Perl的源代码使用UTF-8编码。您需要告诉Perl如何对文本进行编码:

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

谢谢,这对于存储在文件中的程序非常有效,而不是@DaveCross的答案涵盖了命令行中的单行代码。
vktec


14

通过使用CPAN模块,您可以接近“随处都可以做utf8” utf8::all

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

print收到无法打印的内容(不:encoding提供任何图层时,字符大于255 )时,它假定您打算使用UTF-8对其进行编码。在警告问题之后,它会这样做。



0

在西班牙语中,当您开始使用时会发现此错误:

use utf8;

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


1
不。这不是导致错误的原因。该代码均已正确编码为UTF8,但输出文件句柄不知道是这样。
戴夫·克罗斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.