0

我现在对编码方案很感兴趣。我将在下面说明我的问题,请提供您的意见。

问题:我有一些输入字符串,如下面的代码中所述。最终所需的输出是“Křižovnická 190”。[你可以在这里解码]。我正在使用 perl 模块来解码这些字符串。以下是我的测试代码:

use HTML::Entities;
binmode STDOUT,":utf8";
$a = "Křižovnická 190";
decode_entities($a);
print $a."\n";

然而,我得到的输出是“Křiovnická 19”,这意味着“ř”被正确解码,但“ž”不是。我的问题是为什么?然后我尝试了提供 entity2char 哈希的“_decode_entities”方法,但仍然没有成功。

PS:我这里一定要使用 Perl,因为有其他遗留的 API,请在这里帮助我

4

2 回答 2

7

字符“ž”对应ž于 Unicode,而不是ž. 158是cp1252中“ž”的编码。

顺便说一句,克莱门汀很好。

为了清楚起见:

| Grapheme   |         ř         |         ž         |
|------------+-------------------+-------------------|
| Codepoint  | U+0159 (345)      | U+017E (382)      |
| Escape     | ř (ř) | ž (ž) |
|------------+-------------------+-------------------|
| UTF-8      | C5 99 (197 153)   | C5 BE (197 190)   | 
| cp1252     | -                 | 9E    (158)       |
| latin2     | F8    (248)       | BE    (190)       |

更新:

有关详细信息,请参阅Wikipedia 上的HTML 十进制字符渲染。重要的部分是:

(...) 对字符 128-159 的引用通常被宽松的 Web 浏览器解释为对 Windows-1252 字符编码中分配给字节 128-159(十进制)的字符的引用。这违反了 HTML 和 SGML 标准,并且字符已经分配给更高的代码点,因此 HTML 文档作者应该始终使用更高的代码点。例如,对于商标符号 (™),使用™,而不是™

于 2012-10-15T14:04:19.873 回答
2

ž不是指“ž”。它是U+009E PRIVACY MESSAGE,一个控制字符。(158 10 = 9E 16 )

"ž" 是U+017E LATIN SMALL LETTER Z WITH CARON,所以转义是žor ž

一些 Web 浏览器错误地解释具有 80..9F 16 (128..159 10 ) 中的 a 值的数字实体,将数字视为 Unicode 代码点的Windows-1252编码。

| Grapheme           |         ř         |         ž         |
+--------------------+-------------------+-------------------+
| Unicode Code Point | U+0159 (345)      | U+017E (382)      |
| Escape             | ř (ř) | ž (ž) |
+--------------------+-------------------+-------------------+
| cp1252 encoding    | ---               | 9E (158)          |
| Alternate escape*  | ---               | ž (ž)   |

* — Non-standard and buggy behaviour.

这种错误的行为是你想要的。我没有看到实现该行为的模块,因此我们必须编写自己的代码。

use strict;
use warnings;
use open ':std', ':encoding(UTF-8)';

use HTML::Entities qw( );
use Encode         qw( decode );

{
    my %fixes =
        map { chr($_) => decode('cp1252', chr($_)) }
          0x80..0x9F;

    sub decode_entities {
        my $s_ref = defined(wantarray())
            ? do { my ($s) = @_; \$s }
            : \$_[0];

        $$s_ref =~ s{(
            &\#
            (?: 0*([1-9][0-9]*);?
            |   x0*([1-9A-Fa-f][0-9A-Fa-f]*);?
            )
        )}{
            if (defined($2) && length($2) == 3 && exists($fixes{chr($2)})) {
               $fixes{chr($2)}
            } elsif (defined($3) && length($3) == 2 && exists($fixes{chr(hex($3))})) {
               $fixes{chr(hex($3))}
            } else {
               $1
            }
        }exg;

        HTML::Entities::decode_entities($$s_ref);
        return $$s_ref;        
    }
}

print(decode_entities("Křižovnická 190"), "\n");
于 2012-10-15T17:08:26.227 回答