【问题标题】:Perl's use encoding pragma breaking UTF stringsPerl 使用编码编译指示破坏 UTF 字符串
【发布时间】:2011-03-19 15:43:55
【问题描述】:

我对 Perl 和 Encoding pragma 有疑问。

(我在任何地方都使用 utf-8,在输入、输出和 perl 脚本本身。我不想使用其他编码,永远不会。)

但是。当我写

binmode(STDOUT, ':utf8');
use utf8;
$r = "\x{ed}";
print $r;

我看到字符串“í”(这是我想要的 - 什么是 U+00ED unicode char)。但是当我像这样添加“使用编码”杂注时

binmode(STDOUT, ':utf8');
use utf8;
use encoding 'utf8';
$r = "\x{ed}";
print $r;

我看到的只是一个盒子字符。为什么?

此外,当我添加 Data::Dumper 并让 Dumper 像这样打印新字符串时

binmode(STDOUT, ':utf8');
use utf8;
use encoding 'utf8';
$r = "\x{ed}";
use Data::Dumper;
print Dumper($r);

我看到 perl 将字符串更改为 "\x{fffd}"。为什么?

【问题讨论】:

标签: perl


【解决方案1】:

use encoding 'utf8' 坏了。它没有将\x{ed} 解释为代码点U+00ED,而是将其解释为单字节237,然后尝试将其解释为UTF-8。这当然失败了,所以它最终用替换字符 U+FFFD 替换它,字面意思是“�”。

只需坚持使用use utf8 来指定您的源是UTF-8 格式,并使用binmodeopen pragma 来指定文件句柄的编码。

【讨论】:

  • 哦...好的。我不能声称我理解重新解释的原因,但是 perl 中有很多更奇怪的东西。谢谢
  • 据我所知,原因是 use encoding 的设计目的是让人们可以编写 use encoding 'euc-jp'; $r = "\xF1\xD1\xF1\xCC"; 并让它“正确”解释。但这意味着您必须以与$r = "\xC3\xAD"; 相同的样式编写您的UTF-8 字符串。当与 Perl 对 UTF-8 的原生支持(如 $r = "\x{200b}";)结合使用时,这会变得令人困惑,代码 0x80-0xff 的转义符与代码 0x100 及以上代码的转义符的解释不同。
  • 是的,Perl 对 8 位语言环境的支持(use encodinguse locale)应该保持在很长的另一端。
【解决方案2】:

您的实际代码既不需要use encoding 也不需要use utf8 才能正常运行——它唯一依赖的是STDOUT 上的编码层。

binmode(STDOUT, ":utf8");
print "\xed";

是一个同样有效的完整程序,可以做你想做的事情。

use utf8 仅应在程序中的文字字符串中有 UTF-8 时使用——例如如果你写了

my $r = "í";

那么use utf8 将导致该字符串被解释为单个字符 U+00ED 而不是字节序列 C3 AD。

use encoding 不应该被使用,尤其是那些喜欢 Unicode 的人。如果您想更改标准输入/输出的编码,您应该使用-CPERLUNICODE 或您自己的binmode,如果您希望使用编码层自动打开其他句柄,您应该useopen

【讨论】:

  • hobbs:是的,我的代码中有实际的 UTF-8 文字(在正则表达式中)。谢谢。
猜你喜欢
  • 2013-06-17
  • 1970-01-01
  • 2020-11-29
  • 1970-01-01
  • 1970-01-01
  • 2013-08-09
  • 2014-06-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多