3

我有一个像这样的字符串:

Why RUNAS Windows \xee\x80\x80\x45xplorer\xee\x80\x81 Doesn\xe2\x80\x99t 
Work After Installing IE7 St\xc3\xa5le

我通过读取 XML 文件得到。这是一个 UTF-8 字符串。现在我想打印其等效的 unicode 字符,以便得到:

Why RUNAS Windows Explorer Doesn’t Work After Installing IE7 Ståle 

我尝试了一个小程序:

use strict;
use utf8;
use Encode;

my $str = "Why RUNAS Windows \xee\x80\x80\x45xplorer\xee\x80\x81 Doesn\xe2\x80\x99t Work After Installing IE7 St\xc3\xa5le";
print $str;

它奏效了!!

问题是当我试图从文件中读取字符串时,它没有转换。所以以下不会产生 unicode 输出:

use strict;
use utf8;
use Encode;
my $str = <DATA>;
$str = decode("utf8", $str);
open OUT, ">", "o.txt" or die;
binmode(OUT,":utf8");
print OUT $str;
__DATA__
Why RUNAS Windows \xee\x80\x80\x45xplorer\xee\x80\x81 Doesn\xe2\x80\x99t Work After Installing IE7 St\xc3\xa5le
4

3 回答 3

6

您的两个示例之间的区别在于,第一个示例中的反斜杠在编译时被插入为字节,而在第二个示例中,它们是文字文本。在第二个示例中,您正在读取一系列字符“\”、“x”、“e”、“e”,但第一个示例将其转换为内存中的单个 unicode 字符。

如果 XML 文件包含 unicode 字符,Perl 可以很好地读取它们;他们不需要像显示的那样逃脱。

如果您必须将这些 un​​icode 字符保留为字符序列,请考虑使用 CPAN 中的库来解码它们。乍一看,Encode::Escape似乎可以满足您的需求:

#!/usr/bin/perl
use strict;
use warnings;
use Encode::Escape;

while (<DATA>) {
    chomp;
    print decode 'unicode-escape', $_; # convert byte references to (utf-8) bytes
}

__DATA__
Why RUNAS Windows \xee\x80\x80\x45xplorer\xee\x80\x81 Doesn\xe2\x80\x99t
Work After Installing IE7 St\xc3\xa5le

可能还有其他人。

于 2013-01-09T17:13:44.767 回答
4

这很明显:

print "abc\n";   # Prints <abc>

<DATA>;          # Doesn't print <abc>
__DATA__
print "abc\n";

所以这应该不足为奇:

"\x61";          # Evaluates to string <a>

<DATA>;          # Doesn't evaluate to string <a>
__DATA__
"\x61"

您混淆了字符串文字(Perl 运算符)和字符串(字符序列)。readline不会将您的数据文件作为 Perl 代码执行。(即使是这样,你也错过了引号。)如果你想转换你读到的字符串,你将不得不告诉 Perl 来转换它们。

s/ \\x(..) | \\([^a-zA-Z]) | \\(.) /
   defined($1) ? chr(hex($1)) :
   defined($2) ? $2 :
   do { warn "Unknown escape \\$3\n"; "\\$3" }
/sexg;
于 2013-01-09T17:20:22.983 回答
1

使用带评估的替换将每个代码更改为相应的字节。不需要use utf8也不use Encode需要:

#!/usr/bin/perl
use warnings;
use strict;

my $str = <DATA>;
$str =~ s/\\x(..)/chr hex $1/eg;
open my $OUT, '>', 'o.txt' or die $!; # No binmode utf8 - byte semantics needed!
print $OUT $str;

__DATA__
Why RUNAS Windows \xee\x80\x80\x45xplorer\xee\x80\x81 Doesn\xe2\x80\x99t Work After Installing IE7 St\xc3\xa5le
于 2013-01-09T17:13:39.957 回答