呵呵。:-) 这与最近十几个 Perl 版本中对 Unicode 的支持不断增长以及模块\C
使用的正则表达式功能有关,更准确地说,由. 从 2010 年开始阅读perl-unicode 上的这个线程(不要在正则表达式中使用 \C 转义 - 为什么不呢?)以了解背景。URI
URI::Escape
为什么是URI
模块?因为它是用来做表单和 URL 编码的HTTP::Request::Common
。
同时,我写了一个脚本来提醒自己这个问题有多么棘手,特别是因为该URI
模块是一个经常使用的模块:
use 5.010;
use utf8;
# Perl and URI.pm might behave differently when you encode your script in
# Latin1 and drop the utf8 pragma.
use Encode;
use URI;
use Test::More;
use constant C3A8 => 'text=%C3%A8';
use constant E8 => 'text=%E8';
diag "Perl $^V";
diag "URI.pm $URI::VERSION";
my $chars = 'è';
my $octets = encode 'iso-8859-1', $chars;
my $uri = URI->new('http:');
$uri->query_form( text => $chars );
is $uri->query, C3A8, C3A8;
my @exp;
given ( "$^V $URI::VERSION" ) {
when ( 'v5.12.3 1.56' ) { @exp = ( E8, C3A8 ) }
when ( 'v5.10.1 1.54' ) { @exp = ( C3A8, C3A8 ) }
when ( 'v5.10.1 1.58' ) { @exp = ( C3A8, C3A8 ) }
default { die 'not tested :-)' }
}
$uri->query_form( text => $octets );
is $uri->query, $exp[0], $exp[0];
utf8::upgrade $octets;
$uri->query_form( text => $octets );
is $uri->query, $exp[1], $exp[1];
done_testing;
所以我得到(在 Windows 和 Cygwin 上)是:
C:\Windows\system32 :: perl \Opt\Cygwin\tmp\uri.pl
# Perl v5.12.3
# URI.pm 1.56
ok 1 - text=%C3%A8
ok 2 - text=%E8
ok 3 - text=%C3%A8
1..3
和:
MiLu@Dago: ~/comp > perl /tmp/uri.pl
# Perl v5.10.1
# URI.pm 1.54
ok 1 - text=%C3%A8
ok 2 - text=%C3%A8
ok 3 - text=%C3%A8
1..3
更新
您可以手工制作请求正文:
use utf8;
use Encode;
use LWP::UserAgent;
my $chars = 'ölè';
my $octets = encode( 'iso-8859-1', $chars );
my $body = 'text=' .
join '',
map { $o = ord $_; $o < 128 ? $_ : sprintf '%%%X', $o }
split //, $octets;
my $uri = 'http://localhost:8080/';
my $req = HTTP::Request->new( POST => $uri, [], $body );
print $req->as_string;
my $ua = LWP::UserAgent->new;
my $rsp = $ua->request( $req );
print $rsp->as_string;