4

在该Date::Holidays::DK模块中,某些丹麦节日的名称以 Latin1 编码编写。例如,1 月 1 日是“Nytårsdag”。$x为了获得正确的 utf8 编码字符串,我应该在下面做什么?

use Date::Holidays::DK;
my $x = is_dk_holiday(2011,1,1);

use utf8我尝试了and no utf8before/after的各种组合use Date::Holidays::DK,但似乎没有任何效果。我也尝试使用 Encode's decode,但没有运气。进一步来说,

use Date::Holidays::DK;
use Encode;
use Devel::Peek;
my $x = decode("iso-8859-1", 
           is_dk_holiday(2011,1,1)
          );
Dump($x);
print "January 1st is '$x'\n";

给出输出

SV = PV(0x15eabe8) at 0x1492a10
  REFCNT = 1
  FLAGS = (PADMY,POK,pPOK,UTF8)
  PV = 0x1593710 "Nyt\303\245rsdag"\0 [UTF8 "Nyt\x{e5}rsdag"]
  CUR = 10
  LEN = 16
January 1st is 'Nyt sdag'

(在 t 和 s 之间有一个无效字符)。

4

2 回答 2

4

在使用 Date::Holidays::DK 之前/之后使用 utf8 和不使用 utf8,但它似乎没有任何效果。

正确的。utf8pragma 仅表示程序的源代码是用 UTF-8 编写的。

我也尝试使用 Encode 的解码,但没有成功。

你没有正确地理解这一点,你实际上做了正确的事。您现在拥有一串 Perl 字符并且可以对其进行操作。

在 t 和 s 之间有一个无效字符

你也解释错了,其实是å性格。


您想输出 UTF-8,因此缺少编码步骤。

my $octets = encode 'UTF-8', $x;
print $octets;

有关编码主题的介绍,请阅读http://p3rl.org/UNI。您始终必须显式或隐式地解码和编码。

于 2011-07-14T15:03:17.900 回答
2

use utf8只有 perl 解释器/编译器提示您的文件是 UTF-8 编码的。如果您有设置高位的字符串,它会自动将它们编码为 un​​icode。

如果您有一个以 iso-8859-1 编码的变量,则必须对其进行解码。然后你的变量是内部 unicode 格式。那是 utf8 但你不应该关心 perl 内部使用哪种编码。

现在,如果要打印这样的字符串,则需要将 unicode 字符串转换回字节字符串。你需要encode在这个字符串上做一个。如果您不手动perl进行编码,它本身会将其编码回 iso-8859-1。这是默认编码。

在打印变量 $x 之前,您需要对其进行 a$x = encode('UTF-8', $x)操作。

为了正确处理 UTF-8,您始终需要通过 I/O 对每个外部输入进行 decode()。而且你总是需要 encode() 离开你的程序的所有东西。

要更改默认输入/输出编码,您可以使用类似这样的方法。

use utf8;
use open ':encoding(UTF-8)';
use open ':std';

第一行说你的源代码是用 utf8 编码的。第二行说每个输入/输出都应该自动编码为 utf8。需要注意的是,aopen()也以 utf8 模式打开文件。如果您使用二进制文件,则需要binmode()在句柄上调用 a 。

但第二行不会改变对 STDIN、STDOUT 或 STDERR 的处理。第三行将改变这一点。

您可能可以使用 modul utf8:all来简化此过程。但是了解这一切在幕后是如何运作的总是好的。

纠正你的例子。一种可能的方法是:

#!/usr/bin/env perl
use Date::Holidays::DK;
use Encode;
use Devel::Peek;
my $x = decode("iso-8859-1", 
           is_dk_holiday(2011,1,1)
          );
Dump($x);
print encode("UTF-8", "January 1st is '$x'\n");
于 2011-07-14T14:57:02.097 回答