为什么将“€”解码为“€”也会在输出中将“é”变成“É”?
Why does decoding "€" to "€" also turn "é" into "é" in output?
我是 Perl 脚本的新手,在解码字符串时遇到了一些问题:
use HTML::Entities;
my $string='Rémunération €';
$string=decode_entitie($string);
print "$string";
我得到的输出看起来像 Rémunération €
,但它应该像 Rémunération €
。
谁能帮我解决这个问题?
如果您在终端上 运行 此版本的代码(修复了 decode_entities
中的拼写错误,启用了 strict mode and warnings,并添加了一个额外的 print
):
use strict;
use warnings;
use HTML::Entities;
my $string='Rémunération €';
print "$string\n";
$string=decode_entities($string);
print "$string\n";
您应该看到以下输出:
Rémunération €
Wide character in print at test.pl line 7.
Rémunération €
发生以下事件链:
您的代码是用 UTF-8 编写的,但其中没有 use utf8;
,因此 Perl 正在解析您的源代码(尤其是其中的任何字符串文字) 逐字节。因此,字符串文字 'é'
被解析为 双字符 字符串,因为 é
的 UTF-8 编码占用两个字节。
通常,这无关紧要(很多),因为你的 STDOUT
也不是 UTF-8 模式,所以它只需要你给它的任何字节字符串并吐出它逐字节输出,然后您的终端将结果输出解释为 UTF-8(或尝试)。
所以,当你这样做时 print 'é';
Perl 认为你正在以字节模式打印一个两个字符的字符串,并写出两个字节,它们恰好构成了单个字符串的 UTF-8 编码字符 é
.
但是,当您通过 decode_entities()
运行 字符串时,它会将 €
解码为实际的 Unicode €
字符,这不会适合单个字节。
当您尝试打印结果字符串时,Perl 会注意到 "wide" €
字符。它不能将其打印为单个字节,因此,它会回退到将 整个字符串 编码为 UTF-8(并发出警告,如果您启用了这些,就像您应该)。但这会导致 é
s(已经编码,因为 Perl 在解析您的代码时从未对它们进行解码)进行双 UTF8 编码,从而产生您看到的 mojibake 输出。
一个简单的修复方法是将 use utf8;
添加到您的代码中,并将 set all your filehandles(包括 STDIN
/ STDOUT
/ STDERR
)添加到 UTF-默认为 8 模式,例如像这样:
use utf8;
use open qw(:std :utf8);
将这些行添加到上面的测试脚本中,您得到的输出应该是:
Rémunération €
Rémunération €
我是 Perl 脚本的新手,在解码字符串时遇到了一些问题:
use HTML::Entities;
my $string='Rémunération €';
$string=decode_entitie($string);
print "$string";
我得到的输出看起来像 Rémunération €
,但它应该像 Rémunération €
。
谁能帮我解决这个问题?
如果您在终端上 运行 此版本的代码(修复了 decode_entities
中的拼写错误,启用了 strict mode and warnings,并添加了一个额外的 print
):
use strict;
use warnings;
use HTML::Entities;
my $string='Rémunération €';
print "$string\n";
$string=decode_entities($string);
print "$string\n";
您应该看到以下输出:
Rémunération €
Wide character in print at test.pl line 7.
Rémunération €
发生以下事件链:
您的代码是用 UTF-8 编写的,但其中没有
use utf8;
,因此 Perl 正在解析您的源代码(尤其是其中的任何字符串文字) 逐字节。因此,字符串文字'é'
被解析为 双字符 字符串,因为é
的 UTF-8 编码占用两个字节。通常,这无关紧要(很多),因为你的
STDOUT
也不是 UTF-8 模式,所以它只需要你给它的任何字节字符串并吐出它逐字节输出,然后您的终端将结果输出解释为 UTF-8(或尝试)。所以,当你这样做时
print 'é';
Perl 认为你正在以字节模式打印一个两个字符的字符串,并写出两个字节,它们恰好构成了单个字符串的 UTF-8 编码字符é
.但是,当您通过
decode_entities()
运行 字符串时,它会将€
解码为实际的 Unicode€
字符,这不会适合单个字节。当您尝试打印结果字符串时,Perl 会注意到 "wide"
€
字符。它不能将其打印为单个字节,因此,它会回退到将 整个字符串 编码为 UTF-8(并发出警告,如果您启用了这些,就像您应该)。但这会导致é
s(已经编码,因为 Perl 在解析您的代码时从未对它们进行解码)进行双 UTF8 编码,从而产生您看到的 mojibake 输出。
一个简单的修复方法是将 use utf8;
添加到您的代码中,并将 set all your filehandles(包括 STDIN
/ STDOUT
/ STDERR
)添加到 UTF-默认为 8 模式,例如像这样:
use utf8;
use open qw(:std :utf8);
将这些行添加到上面的测试脚本中,您得到的输出应该是:
Rémunération €
Rémunération €