我是Perl脚本的新手,我在解码字符串方面遇到了一些问题:
use HTML::Entities;
my $string='Rémunération €';
$string=decode_entitie($string);
print "$string";
我得到的输出看起来像Rémunération €
,看起来应该是Rémunération €
。
有人可以帮我解决这个问题吗?
答案 0 :(得分:8)
如果您运行此版本的代码(在decode_entities
修复了错误,strict模式并启用了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编码{ {1}}。
但是,当您通过é
运行字符串时,它会将decode_entities()
解码为实际的Unicode €
字符,该字符不适合单个字节。
当您尝试打印生成的字符串时,Perl会注意到“宽”€
字符。它无法将其打印为单个字节,因此它会回退到将整个字符串编码为UTF-8(并发出警告,如果您启用了这些,则应该如此)。但是这会导致€
s(已经编码,因为Perl在解析代码时从未对其进行解码)以获得双UTF8编码,从而生成您看到的mojibake输出。
一个简单的解决方法是将é
添加到您的代码中,并将set all your filehandles(包括use utf8;
/ STDIN
/ STDOUT
)添加到UTF-8模式默认情况下,例如像这样:
STDERR
将这些行添加到上面的测试脚本之前,你得到的输出应该是:
use utf8;
use open qw(:std :utf8);