Perl 认为你的源文件被编码为 Latin-1,直到你告诉它use utf8
. 如果我们这样做,字符串"ضثصثضصثشس"
不包含一些混乱的字节,而是一串代码点。
需要一串代码点(不是字节!),对uri_escape_utf8
它们进行编码,然后对它们进行 URI 转义。因此,正确的做法是
use utf8;
use URI::Escape;
print uri_escape_utf8("ضثصثضصثشس"), "\n";
输出:%D8%B6%D8%AB%D8%B5%D8%AB%D8%B6%D8%B5%D8%AB%D8%B4%D8%B3
如果我们失败了use utf8
,那么uri_escape_utf8
会得到一个字节串(它被意外地以 UTF8 编码),所以我们应该使用uri_escape
:
die "This is the wrong way to do it";
use URI::Escape;
print uri_escape("ضثصثضصثشس"), "\n";
它产生与上述相同的输出——但只是偶然的。
使用uri_escape_utf8
whith 字节串(将解码为阿拉伯字符)会产生完全错误的结果
%C3%98%C2%B6%C3%98%C2%AB%C3%98%C2%B5%C3%98%C2%AB%C3%98%C2%B6%C3%98%C2%B5%C3%98%C2%AB%C3%98%C2%B4%C3%98%C2%B3
因为这有效地对数据进行了双重编码。它与
use utf8;
use URI::Escape;
use Encode;
print uri_escape(encode "utf8", encode "utf8", "ضثصثضصثشس"), "\n";
编辑:所以你使用了 CP-1256,这是一种不可移植的单字节编码。它无法对任意 Unicode 字符进行编码,因此应避免与其他 pre-Unicode 编码一起使用。你没有声明你的编码,所以 perl 认为你的意思是 Latin-1。这意味着您所看到的"ضثصثضصثشس"
实际上是 byte stream D6 CB D5 CB D6 D5 CB D4 D3
,它在 Latin-1 中解码为一些不可打印的垃圾。
编辑:所以你想解码命令行参数。Encode::Locale
模块应该管理这个。在从 访问任何参数之前@ARGV
,请执行
use Encode::Locale;
decode_argv(Encode::FB_CROAK); # possibly: BEGIN { decode_argv(...) }
或使用locale
它提供的伪编码:
my $decoded_string = decode "locale" $some_binary_data;
将此用作解码所有输入并始终对输出进行编码的整体策略的一部分。