perl - 相同的代码,不同机器上关于 UTF8 字符的不同结果

标签 perl utf-8

我有这个代码:

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- 构建的 perl 5,版本 16,subversion 3 (v5.16.3)多 ld

HTML::Entities 的版本在两台机器上是相同的:

    Installed: 3.69
    CPAN:      3.69  up to date

我的开发机器运行 CentOS 5.8 版(最终版),UAT 机器运行 Red Hat Enterprise Linux Server 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=

更新:

我在 perl developers 上发布了这个问题的链接在 facebook 上分组并从那里得到了一些非常有用的想法:比较两个系统上的输出字节。如果它们相同,则为显示问题。他们是。现在,有不止一种方法可以做到这一点:

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 连接)。

最佳答案

命令终端期望的编码是不同的。如果你想打印 UTF-8,你必须将两个终端都设置为期望 UTF-8,例如罗马尼亚语

LANG=ro_RO.UTF-8

以及将 STDOUT 设置为 encode 在您的 Perl 中以这种方式输出,例如

binmode STDOUT, ':encoding(utf-8)'

更新

我可以解释正在发生的事情,虽然我不太确定为什么会这样。

取字符串的第一个字符:"\x{010C}",这是一个大写的 C 重音符。它被 Perl 编码为两个八位字节代码 "\x{C4}\x{8C}" 并发送到终端,终端在您的开发机器上解码并显示它正确。

但是,在您的测试机器上,终端正在解码编码字符的第一个八位字节 - C4 - 就好像它是 ISO-8859-1,一个大写的 A 变音符号。第二个八位字节 - 8C - 被忽略,因为它是该编码中的无效字符。

因此您需要更改终端使用的代码页。方法是按照我的描述设置 LANG,但如果您的 locale 设置正确,我无法解释为什么它不起作用。

关于perl - 相同的代码,不同机器上关于 UTF8 字符的不同结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25527512/

相关文章:

perl - 如何判断我的程序是否正在通过管道传输到另一个 (Perl)

perl - 检测单个 CJK 字符

python - 将每个字典值转换为 utf-8(字典理解?)

c++ - 在终端中正确输出 c++ windows wstring 日志

java - Unicode 字符 ""有什么特别之处,以至于它破坏了基于大括号的解析器逻辑?

perl - Perl 的 Getopt::Long 可以解析我没有提前定义的参数吗?

regex - 为什么我的 Perl 正则表达式会导致无限循环?

perl - 使用 CPAN 将 Perl 模块安装到特定目录,当几个模块出现在使用中时

java - 使用java编写UTF-8文件

regex - 使用 Perl 反斜杠序列的 Apache 重写规则不起作用