Perl:latin1模块中的字符串文字 - 我想要utf8

时间:2011-07-14 14:11:08

标签: perl encoding utf-8 perl-module latin1

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

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

我在use utf8之前/之后尝试了no utf8use Date::Holidays::DK的各种组合,但它似乎没有任何效果。我也试图使用Encode的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之间的字符无效)。

2 个答案:

答案 0 :(得分:4)

  

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

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

  

我也试过使用Encode的解码,没有运气。

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

  

t和s之间的字符无效

你也解释了这个错误,实际上是å字符。


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

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

请阅读http://p3rl.org/UNI以了解编码主题的介绍。你总是必须明确地或隐含地解码和编码。

答案 1 :(得分:2)

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

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

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

在打印变量$ x之前,您需要在其上执行$x = encode('UTF-8', $x)

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

要更改默认的输入/输出编码,您可以使用类似的内容。

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

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

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

您可以使用模块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");