92

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

4

6 回答 6

115

如果没有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. 它会这样说:

(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 是一个大而复杂的领域。正如您所看到的,许多简单的程序似乎都在做正确的事情,但原因却是错误的。当您开始修复程序的一部分时,事情通常会变得更糟,直到您修复了所有程序。

于 2013-03-05T10:56:27.503 回答
83

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

use open ':std', ':encoding(UTF-8)';
于 2013-03-04T20:34:08.783 回答
19

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

binmode STDOUT, ":utf8";
于 2014-02-17T21:18:33.840 回答
14

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

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

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

于 2013-03-04T21:25:43.727 回答
6

你可以用这个,

perl -CS filename.

它还将终止该错误。

于 2015-04-09T10:40:39.863 回答
0

在西班牙语中,除了开始使用之外,您还会发现此错误:

use utf8;

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

于 2015-05-23T14:15:31.313 回答