ChatGPT解决这个技术问题 Extra ChatGPT

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

“为什么这不起作用?”它确实有效,但根据我对 Unicode 的经验,那里有很多非常糟糕的程序,看起来它们正在工作。当你修复一件事,让代码稍微少一点错误时,结果似乎更糟。只有当您修复最后一部分时,一切才会再次看起来不错。

D
Dave Cross

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


如果不在一个衬里 perl 中,如何拼写 -Mutf8
@LeiYang:use utf8;
i
ikegami

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

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

谢谢,这适用于存储在文件中的程序,而不是命令行上的单行代码,@DaveCross 的答案涵盖了这一点。
P
Peter Mortensen

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

binmode STDOUT, ":utf8";

use open ':std', ':encoding(UTF-8)'; 正如另一个答案所建议的那样,它对 STDOUT 执行此操作,但也将 STDERR 和 STDIN 标记为 UTF-8,因此您以一个语句的价格获得三个。另请参阅stackoverflow.com/a/42194059
同意。这甚至更好。
我无法让这个简单的程序在运行 Perl 5.32 的 Windows 10 PC 上正确打印花引号。是否缺少某些东西,或者它只是 Windows 无法正确执行的另一件事? BEGIN {binmode STDOUT, ":utf8";} print "\x{201C}in curly quotes\x{201D}\n";
i
ikegami

通过使用 CPAN 模块 utf8::all,您可以接近“在任何地方都使用 utf8”。

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

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


K
Karthikeyan.R.S

你可以用这个,

perl -CS filename.

它还将终止该错误。


只有这有帮助
如果您不只是运行 Oneliner,请参见此处:perldoc.perl.org/…
P
Peter Mortensen

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

use utf8;

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


不,这不是导致错误的原因。该代码全部正确编码为 UTF8,但输出文件句柄不知道它是。