在Perl中将UTF8字符串转换为ASCII

Mar*_*k C 12 perl ascii utf-8

我已经尝试了Google和StackOverflow推荐的所有内容(我能找到),包括使用Encode.我的代码工作,但它只使用UTF8,我得到广泛的字符警告.我知道如何解决这些警告,但我没有将UTF8用于其他任何事情,所以我只想转换它而不必调整我的其余代码来处理它.这是我的代码:

my $xml = XMLin($content);
# Populate the @titles array with each item title.
my @titles;
for my $item (@{$xml->{channel}->{item}}) {
    my $title = Encode::decode_utf8($item->{title});
    #my $title = $item->{title};
    #utf8::downgrade($title, 1);
    Encode::from_to($title, 'utf8', 'iso-8859-1');
    push @titles, $title;
}
return @titles;
Run Code Online (Sandbox Code Playgroud)

注释掉你可以看到我尝试过的其他一些东西.我很清楚我不知道我在这做什么.我只是想用一个普通的旧ASCII字符串结束.任何想法将不胜感激.谢谢.

szb*_*int 19

答案取决于您希望如何使用标题.有三种基本方法:

  • 表示UTF-8编码字符串的字节.

如果要将UTF-8编码的字符串存储在应用程序之外,无论是在磁盘上还是通过网络发送或在程序范围之外的任何内容,都应使用此格式.

  • 一串Unicode字符.

字符的概念是Perl的内部.执行时Encode::decode_utf8,会尝试将一堆字节转换为字符串,如Perl所示.除了通过在输入上解码UTF-8字节并在输出上将它们编码为UTF-8字节之外,Perl VM(以及编写Perl代码的程序员)不能外化该概念.例如,你的程序接收两个字节作为输入,你知道它们代表UTF-8编码的字符,比如说0xC3 0xB6.在这种情况下,decode_utf8返回一个表示,而不是两个字节,看到一个字符:ö.

然后,您可以继续在Perl中操作该字符串.为了进一步说明差异,请考虑以下代码:

my $bytes = "\xC3\xB6";
say length($bytes); # prints "2"
my $string = decode_utf8($bytes);
say length($string); # prints "1"
Run Code Online (Sandbox Code Playgroud)
  • ASCII的特例,UTF-8的子集.

    ASCII是Unicode的一个非常小的子集,其中该范围内的字符由单个字节表示.将Unicode转换为ASCII本身就是有损操作,因为大多数Unicode字符不是ASCII字符.当你试图强制使用Unicode时,你要么被迫删除字符串中不是ASCII的每个字符,要么尝试从Unicode字符映射到它们最接近的ASCII等价物(这在绝大多数情况下是不可能的)字符串到ASCII.

由于您有广泛的字符警告,这意味着您正在尝试操作(可能输出)不能表示为ASCII或ISO-8859-1的Unicode字符.

如果您不需要将XML文档中的标题作为字符串进行操作,我建议您将其保留为UTF-8字节(我提到您应该注意不要在字符串中混合使用字节和字符).如果您确实需要对其进行操作,则解码,操作和输出将其编码为UTF-8.

如要进一步了解,请使用perldoc学习perlunitut,perlunifaq,perlunicode,perluniintro,和Encode.

  • 如果你必须将UTF-8转换为ASCII,你需要[Text :: Unidecode](http://search.cpan.org/perldoc?Text::Unidecode). (2认同)

Joh*_*n C 6

虽然这是一个老问题,但我只花了几个小时(!)试图做或多或少相同的事情!即:从UTF-8 XML文件中读取数据,并将该数据转换为Windows-1252代码页(我也可以使用Latin1,ISO-8859-1等),以便能够创建带有重音字母的文件名.

经过大量的实验,甚至更多的搜索,我终于设法让转换工作."技巧"是使用Encode :: encode而不是Encode :: decode.

例如,给定原始问题中的代码,从UTF-8转换的正确(或至少一种: - )方式将是:

my $title = Encode::encode("Windows-1252", $item->{title});
Run Code Online (Sandbox Code Playgroud)

要么

my $title = Encode::encode("ISO-8859-1", $item->{title});
Run Code Online (Sandbox Code Playgroud)

要么

my $title = Encode::encode("<your-favourite-codepage-here>", $item->{title});
Run Code Online (Sandbox Code Playgroud)

我希望这可以帮助其他人遇到类似问题!