当我遇到 Unicode 问题时,我正在尝试编写一个测试查询字符串解析的示例。简而言之,字母“Omega”(Ω) 似乎没有被正确解码。
- 统一码:U+2126
- 3字节序列:\xe2\x84\xa6
- URI 编码:%E2%84%A6
所以我编写了这个测试程序来验证我可以使用 URI::Encode“解码”unicode 查询字符串。
use strict;
use warnings;
use utf8::all; # use before Test::Builder clones STDOUT, etc.
use URI::Encode 'uri_decode';
use Test::More;
sub parse_query_string {
my $query_string = shift;
my @pairs = split /[&;]/ => $query_string;
my %values_for;
foreach my $pair (@pairs) {
my ( $key, $value ) = split( /=/, $pair );
$_ = uri_decode($_) for $key, $value;
$values_for{$key} ||= [];
push @{ $values_for{$key} } => $value;
}
return \%values_for;
}
my $omega = "\N{U+2126}";
my $query = parse_query_string('alpha=%E2%84%A6');
is_deeply $query, { alpha => [$omega] }, 'Unicode should decode correctly';
diag $omega;
diag $query->{alpha}[0];
done_testing;
以及测试的输出:
query.t ..
not ok 1 - Unicode should decode correctly
# Failed test 'Unicode should decode correctly'
# at query.t line 23.
# Structures begin differing at:
# $got->{alpha}[0] = 'â¦'
# $expected->{alpha}[0] = 'Ω'
# Ω
# â¦
1..1
# Looks like you failed 1 test of 1.
Dubious, test returned 1 (wstat 256, 0x100)
Failed 1/1 subtests
Test Summary Report
-------------------
query.t (Wstat: 256 Tests: 1 Failed: 1)
Failed test: 1
Non-zero exit status: 1
Files=1, Tests=1, 0 wallclock secs ( 0.03 usr 0.01 sys + 0.05 cusr 0.00 csys = 0.09 CPU)
Result: FAIL
在我看来 URI::Encode 可能在这里被破坏了,但是切换到 URI::Escape 并使用 uri_unescape 函数会报告同样的错误。我错过了什么?
最佳答案
URI 编码的字符简单地表示 utf-8 序列,而 URI::Encode 和 URI::Escape 只是将它们解码为 utf-8 字节字符串,它们都没有将字节串解码为 UTF-8(这是一个作为通用 URI 解码库的正确行为)。
换句话说,您的代码基本上是这样的:
is "\N{U+2126}", "\xe2\x84\xa6"
并且会失败,因为在比较时,perl 将后者升级为 3 个字符长度的 latin-1 字符串.
您必须在 uri_decode
之后使用 Encode::decode_utf8
手动解码输入值,或者比较编码后的 utf8 字节序列。
关于perl - 在 Perl 中测试查询字符串 unicode 处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10086420/