【问题标题】:Unexpected behavior of HTML::EntitiesHTML::Entities 的意外行为
【发布时间】:2016-05-02 14:17:39
【问题描述】:

我是 Perl 的 HTML::Entities 例程 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

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

发生了什么事?

【问题讨论】:

    标签: perl unicode character-encoding ascii


    【解决方案1】:

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

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

    1. 手动,使用Encode 模块
    2. 自动使用正确的 I/O 层

    我更喜欢第二种选择,因为它不那么乏味。为此,我们只需在STDOUT 上致电binmode()

    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
    

    您可以看到字符 6873(分别为 hs)之间有代码点 2019 (right single quotation mark),并且也是6573 之间的a0 (non-breaking space),即es

    除了前面提到的perlunicode 参考之外,如果您有兴趣了解有关 Perl 如何处理 Unicode 和一般。

    【讨论】:

      猜你喜欢
      • 2014-07-30
      • 2016-05-27
      • 2013-06-07
      • 2016-10-25
      • 1970-01-01
      • 2016-11-13
      • 2020-10-04
      • 2016-07-16
      • 2016-05-10
      相关资源
      最近更新 更多