виктор ефимов «Unicode в perl и как перевести на него...
-
Upload
nikolay-mishin -
Category
Software
-
view
291 -
download
0
Transcript of виктор ефимов «Unicode в perl и как перевести на него...
2
Перейти с CP1251 на Unicode.В Web приложении на Perl
Сотни тысяч строк Perl кода
Сайт, бэкофис, много скриптов
Регистрация IDN доменов на разных языках.
Чтобы работать с текстом на разных языках одновременно.
to unicode or not to unicode
Даже для одного языка - однобайтные кодировки - не вариант
4
use Modern::Perl;print "YES\n" if "\x85" =~ /^\s+$/;__END__YES
to unicode or not to unicode
lc(), uc(), \w \W \s \S и т.д. могут не работать
5
\x85 в cp1251 это
Текстовые строкиВнутренний
форматКак интерпретируются Как
интерпретируется 0xD0 0xAF
С флагом UTF-8
(Unicode)
Строка считается последовательностью
unicode символов, закодированных в UTF-8
Один символ "Я" (unicode U+042F)
Без флага UTF-8
Каждый байт - один символ
Два символа с кодами (U+00D0 U+00AF )
6
Сделать так чтобы один и тот код работал со строками в разных форматах (unicode или cp1251)
Работаем одновременно в разных кодировках
В зависимости от конфига, приложение сможет работать то в одной кодировке то в другой
7
"Старый" код будет совместим только с режимом работы в формате cp1251
sub func {my ($s) = @_; # $s либо cp1251 либо unicodeto_unicode($s); # теперь $s - точно unicode$s =~ s/(\W+)/_/g; # текстовая операцияfrom_unicode($s); # $s в том формате что и былоreturn $s;
}
Работаем одновременно в разных кодировках
8
Как выглядит такой код
sub func {my ($s) = @_; # $s либо cp1251 либо unicode$s = Encode::decode("CP1251", $s); # to_unicode($s)$s =~ s/(\W+)/_/g; # текстовая операция$s = Encode::encode("CP1251", $s); # from_unicode($s)return $s;
}
Работаем одновременно в разных кодировках
9
Как этот код работает в режиме CP1251
sub func {my ($s) = @_; # $s либо cp1251 либо unicode
# to_unicode($s) - ничего не делает!$s =~ s/(\W+)/_/g; # текстовая операция
# from_unicode($s) - ничего не делает!return $s;
}
Работаем одновременно в разных кодировках
10
Как этот код работает в режиме Unicode
Работаем одновременно в разных кодировках
11
Режим to_unicode from_unicode
CP1251 CP1251 -> UNICODE
UNICODE -> CP1251
Unicode NOP NOP
Работаем одновременно в разных кодировках
12
Режим to_unicode from_unicode to_cp1251 from_cp1251
CP1251 CP1251 -> UNICODE
UNICODE -> CP1251
NOP NOP
Unicode NOP NOP UNICODE -> CP1251
CP1251 -> UNICODE
$value =~ /Привет/i # исходник в CP1251
Что ещё нужно сделать с кодом
13
Строковые константы
use utf8;$value =~ /Привет/i; # исходник в UTF-8
Было
Стало
Что ещё нужно сделать с кодом
15
Ввод-вывод
to_unicode($str);open my $fh, ">:encoding(UTF-8)", $filename;print $fh $str;
Тестирование
16
package MyClass;use utf8;sub myfunc {
my ($x, $data) = @_;do_something($data);if ($x == 42) {
do_even_more($data);$s =~ s/Ё/Е/g;
}}
Тестирование
17
package MyClass;use utf8;sub myfunc {
my ($x, $data) = @_;do_something($data);if ($x == 42) { # Always TRUE
do_even_more($data);$s =~ s/Ё/Е/g;
}}
Test::Spec
18
Тестирование
Test::Spec::Mocks
$myobj->expects('do_something')->with("Привет")->returns("Тест");
MyApp->config( encoding => 'UTF-8' )
19
Catalyst
Content-Type: text/html; charset=utf-8
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Только байты. Никакого текста.
22
Redis, Redis::Fast
Perl не может отличить байты от текста
Используем сериализацию. Например Storable.только сериализация которая восстанавливает все скаляры в оригинальном виде
26
Сложные структуры данныхmy $dataref = +{
x => [1,2,3,"тест"],y => { a => 42 },
};to_unicode_recursive($dataref);
27
Сложные структуры данных
sub myfunc {my ($str) = @_;to_unicode_recursive $str; # в unicode$is_greetings = $str->{field} =~ /Привет/i;die if rand() > 0.5; # проблемаfrom_unicode_recursive $str; # обратноreturn $is_greetings;
}
28
Сложные структуры данных
sub myfunc {my ($str) = @_;my $str_u = to_unicode_clone $str; # в unicodemy $is_greetings = $str_u->{field} =~ /Привет/i;die if rand() > 0.5; # нет проблем!# обратно перекодировать не нужноreturn $is_greetings;
}
29
Сложные структуры данныхmy $dataref = +{
x => [1,2,3,"тест"],y => { a => 42 },z => bless { field => "привет"}, 'MyObject'
};to_unicode_recursive($dataref); # ошибка
30
Запуск на productionModule1.pm (unicode ok)
Module2.pm (unicode ok)
Module3.pm (unicode ok)
Module4.pm (legacy)
script1.pl
script2.pl
ps#2618 unicode
ps#2621 unicode
ps#2622 CP1251
ps#2626 CP1251
ps#2624 CP1251
В общем Redis сервере кэшируются фрагменты html в разных кодировках
31
Запуск на production
Веб приложение пишет в базу символы, которых нет в cp1251, значит cp1251 процессы их “не увидят”
Написание возможно в 2 строкиПлашку регулировать по длине текста
Вывод или посыл зрителюСпасибо!Буду рад ответитьна ваши вопросы!
E-mail:[email protected]
32