好的,这应该非常简单,但我已经搜索了所有答案并阅读了以下主题: How do I find the length of a Unicode string in Perl?
这对我没有帮助。我知道如何让Perl将字符串常量视为UTF-8并返回正确数量的字符(而不是字节),但是当Perl通过我的AJAX调用接收字符串时,它会以某种方式起作用。
下面,我将以unicode发布三个希腊字母Alpha,Beta和Omega。 Perl告诉我长度是6(字节),它应该告诉我只有3(字符)。如何获得正确的字符数?
#!/usr/bin/perl
use strict;
if ($ENV{CONTENT_LENGTH}) {
binmode (STDIN, ":utf8");
read (STDIN, $_, $ENV{CONTENT_LENGTH});
s{%([a-fA-F0-9]{2})}{ pack ('C', hex ($1)) }eg;
print "Content-Type: text/html; charset=UTF-8\n\nReceived: $_ (".length ($_)." chars)";
exit;
}
print "Content-Type: text/html; charset=UTF-8\n\n";
print qq[<html><head><script>
var oRequest;
function MakeRequest () {
oRequest = new XMLHttpRequest();
oRequest.onreadystatechange = zxResponse;
oRequest.open ('POST', '/test/unicode.cgi', true);
oRequest.send (encodeURIComponent (document.oForm.oInput.value));
}
function zxResponse () {
if (oRequest.readyState==4 && oRequest.status==200) {
alert (oRequest.responseText);
}
}
</script></head><body>
<form name="oForm" method="POST">
<input type="text" name="oInput" value="αβΩ">
<input type="button" value="Ajax Submit" onClick="MakeRequest();">
</form>
</body></html>
];
顺便说一句,代码是内部简化的(我知道如何进行跨浏览器的AJAX调用等)并且使用CGI Perl模块不是一个选项。
答案 0 :(得分:8)
在调用length
之前解码此字符串。例如:
use Encode;
my $utf_string = decode_utf8($_); ## parse string to find utf8 octets
print length($utf_string);
$ string = decode_utf8($ octets [,CHECK]);
相当于$ string = decode(“utf8”,$ octets [,CHECK])。由$ octets表示的八位字节序列从UTF-8解码为逻辑字符序列。并非所有八位字节序列都形成有效的UTF-8编码,因此此调用可能会失败。有关CHECK,请参阅处理格式错误的数据。
答案 1 :(得分:4)
对于完成此操作的“本机”方式,您可以在使用此方法复制时进行转换:
将内存文件中的模式设置为所需模式并从中读取。这将在读取字符时进行转换。
use strict;
use warnings;
my $utf_str = "αβΩ"; #alpha; bravo; omega
print "$utf_str is ", length $utf_str, " characters\n";
use open ':encoding(utf8)';
open my $fh, '<', \$utf_str;
my $new_str;
{ local $/; $new_str=<$fh>; }
binmode(STDOUT, ":utf8");
print "$new_str ", length $new_str, " characters";
#output:
αβΩ is 6 characters
αβΩ 3 characters
如果要转换编码,可以使用:
my $utf_str = "αβΩ";
print "$utf_str is ", length $utf_str, " characters\n";
binmode(STDOUT, ":utf8");
utf8::decode($utf_str);
print "$utf_str is ", length $utf_str, " characters\n";
#output:
αβΩ is 6 characters
αβΩ is 3 characters
但是你不应该回避Encode
。
答案 2 :(得分:2)
utf8::decode
。它是核心,没有内存使用惩罚:
基本无操作循环内存使用:
$ perl -e 'sleep 1 while 1' &
[1] 17372
$ ps u | grep 17372 | grep -v grep
okram 17372 0.0 0.1 5464 1172 pts/0 S 01:24 0:00 perl -e [...]
Encode的内存使用情况:
$ perl -MEncode -e 'sleep 1 while 1' &
[1] 17488
$ ps u | grep 17488 | grep -v grep
okram 17488 0.7 0.2 6020 2224 pts/0 S 01:27 0:00 perl [...]
建议的方式:
$ perl -e '$str="ææææ";utf8::decode $str;print length $str,"\n\n";
sleep 1 while 1' &
[1] 17554
$ 4
$ ps u | grep 17554| grep -v grep
okram 17554 0.0 0.1 5464 1176 pts/0 S 01:28 0:00 perl -e [...]
如您所见,对于该utf8字符串,utf8::decode
之后的字符串长度为4,并且内存使用率与基线(1)基本相同。编码似乎消耗了更多的内存......