HTML :: Entities的意外行为

时间:2016-01-26 03:41:05

标签: perl unicode character-encoding ascii

我是Perl的HTML ::实体例程decode_entities()的新手用户 转换从新闻媒体网站上删除的头条新闻。

这是一个很好的结果:

之前:Texas grand jury clears Planned Parenthood, indicts its accusers
之后:Texas grand jury clears Planned Parenthood, indicts its accusers

但这是一个令人费解的结果:

之前:Big changes could be coming to Utah’s criminal justice system
之后:Big changes could be coming to Utahâs criminal justice system

请注意,’代码不仅没有转换为单引号, 也没有被解码为空格,与第一个示例不同。

发生了什么?

1 个答案:

答案 0 :(得分:2)

第一个和第二个示例之间的区别在于第一个示例不包含255以上的任何代码点,而第二个示例则不包含。因此,第一个字符串可以根据系统的原生8位字符集显示(很可能是ISO 8859-1 / Latin 1),但第二个字符串不能。根据{{​​3}},其原因在于“使用大于255的代码点意味着整个字符串的Unicode”。

由于您现在在字符串中有Unicode字符,因此您需要正确编码文本以进行输出,否则您将看到“奇怪的字符”(就像您示例中的那些!)。由于你没有提供perlunicode,我不确定你的输出方法是什么,但让我们假设STDOUT让事情变得简单。有几种不同的方法可以将文本编码为八位字节流:

  1. 手动,使用Minimal, Complete, and Verifiable example模块
  2. 自动使用正确的I / O层
  3. 我更喜欢第二种选择,因为它不那么乏味。为此,我们只需在STDOUT上致电Encode

    use strict;
    use warnings;
    use HTML::Entities;
    
    my $str = 'Big changes could be coming to Utah’s criminal justice system';
    my $decoded = decode_entities($str);
    
    binmode(STDOUT, ':encoding(UTF-8)');
    printf("%s\n%vx\n", $decoded, $decoded);
    

    输出:

    $ perl foo.pl
    Big changes could be coming to Utah’s criminal justice system
    42.69.67.20.63.68.61.6e.67.65.73.20.63.6f.75.6c.64.20.62.65.20.63.6f.6d.69.6e.67.20.74.6f.20.55.74.61.68.2019.73.20.63.72.69.6d.69.6e.61.6c.20.6a.75.73.74.69.63.65.a0.73.79.73.74.65.6d
    

    您可以看到字符201968之间存在代码点73binmode())( h s < / em>,分别),以及a065之间的73right single quotation mark),它们将是 e 小号

    除上述non-breaking space引用外,如果您有兴趣了解详情,还应阅读perlunicodeperluniintro(简短!)和perlunitut Perl如何处理Unicode和字符编码。