【发布时间】:2014-08-27 12:40:57
【问题描述】:
我有这个代码:
use strict;
use warnings;
use utf8;
use HTML::Entities;
use feature 'say';
binmode STDOUT, ':encoding(utf-8)';
my $t1 = "Česká Spořitelna - Q3 2014";
my $t2 = "Česká Spořitelna - Q3 2014";
say decode_entities($t1);
say decode_entities($t2);
在我的开发机器上执行时,输出:
Česká Spořitelna - Q3 2014
Česká Spořitelna - Q3 2014
当在 UAT 机器上执行时(Aser 验收测试),输出:
Äeská SpoÅitelna - Q3 2014
Äeská SpoÅitelna - Q3 2014
现在,在两台机器上,当我运行 perl -v 时,我们有 这是为 x86_64-linux-thread-multi-ld 构建的 perl 5,版本 16,subversion 3 (v5.16.3)
并且HTML::Entities的版本在两台机器上都是一样的:
Installed: 3.69
CPAN: 3.69 up to date
我的开发机器运行CentOS release 5.8 (Final),UAT机器运行Red Hat Enterprise Linux Server release 5.8 (Tikanga)
EDIT(关于locale 命令的输出)
它的输出在两台机器上是相同的:
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
更新:
我在 facebook 的 perl developers 组上发布了这个问题的链接,并从那里得到了一些非常有用的想法:比较两个系统上的输出字节。如果它们相同,则为显示问题。他们是。现在,有不止一种方法可以做到这一点:
1)
say join ':', map { ord } split //, decode_entities($t1);
say join ':', map { ord } split //, decode_entities($t2);
在两个系统上都显示268:101:115:107:225:32:83:112:111:345:105:116:101:108:110:97:32:45:32:81:51:32:50:48:49:52,所以字节是一样的
2) 将$t1 和$t2 输出打印到每个系统上的文件,然后对这些文件运行hexdump -C 并比较输出。这个方法也显示文件的内容是一样的
结论
这是一个显示问题 - 控制台(putty)无法正确显示字符。
当我们在数据库中添加这些字符时,我们遇到了这个问题,我想我设法用上面的代码将它隔离了。您的回答(以及一些来自 fb 的回答)帮助我发现 decode_entities() 按预期工作,而我们的问题出在其他地方(很可能在 mysql 表字符集或 mysql 连接处)。
【问题讨论】:
-
检查两台机器上
locale命令的输出。 -
终端需要 UTF-8 以外的内容,但您输出的是 UTF-8。调整终端期望的编码或调整使用的编码使其匹配。
-
你是如何连接到这些机器的?您是否为两者使用相同的终端程序?它是否具有特定于每个主机的设置?
-
检查 shell 如何接受 utf8 i/o。例如试试
touch ČeskáKočka和ls。使用 bash?尝试设置set convert-meta off;set input-meta on;set output-meta on