转换字符串中的字符

时间:2013-01-09 17:02:29

标签: string perl

我有一个字符串:

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

3 个答案:

答案 0 :(得分:5)

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

如果XML文件包含unicode字符,Perl可以很好地读取它们;它们不需要如图所示进行转义。

如果必须将这些unicode字符保留为字符序列,请考虑使用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

可能还有其他人。

答案 1 :(得分: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;

答案 2 :(得分:1)

使用带评估的替换将每个代码更改为相应的字节。不需要use utf8use 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