Как получить длину строки ввода Perl Unicode через Ajax или CGI? - PullRequest
4 голосов
/ 14 сентября 2010

Хорошо, это должно быть действительно просто, но я искал ответ повсюду и также прочитал следующую ветку: Как найти длину строки Unicode в Perl?

Это мне не помогает.Я знаю, как заставить Perl обрабатывать строковую константу как UTF-8 и возвращать правильное количество символов (вместо байтов), но почему-то это не работает, когда Perl получает строку через мой вызов AJAX.

Ниже я выкладываю три греческие буквы Альфа, Бета и Омега в юникоде.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="&#x03B1;&#x03B2;&#x03A9;">
            <input type="button" value="Ajax Submit" onClick="MakeRequest();">
        </form>
    </body></html>
];

Кстати, код существенно упрощен (я знаю, как сделать кросс-браузерный вызов AJAX и т. Д.), И использование модуля CGI Perl не опция.

Ответы [ 3 ]

8 голосов
/ 14 сентября 2010

Вы декодируете эту строку перед вызовом 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, поэтому возможен сбой этого вызова. ПРОВЕРИТЬ, см. Обработка искаженных данных.

4 голосов
/ 14 сентября 2010

Для «нативного» способа сделать это вы можете конвертировать при копировании следующим способом:

Установите режим для файла в памяти на нужный режим и считайте его. Это сделает преобразование по мере чтения символов.

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 голосов
/ 14 сентября 2010

используйте utf8::decode, если вы знаете, что строка находится в utf8.Это ядро, и нет потери за использование памяти:

Базовое использование памяти без цикла:

$ 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 [...]

Использование памяти с кодированием:

$ 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::decode равна 4 для этой строки utf8, а использование памяти в значительной степени совпадает с базовым значением while (1).Кажется, кодирование занимает немного больше памяти ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...