Top Banner
1 1 Unicode в Perl и как перевести на него систему Виктор Ефимов
32

виктор ефимов «Unicode в perl и как перевести на него систему» (yapc russia 2014, спб)

Apr 14, 2017

Download

Software

Nikolay Mishin
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

11

Unicode в Perl и как перевести на него систему

Виктор Ефимов

Page 2: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

2

Перейти с CP1251 на Unicode.В Web приложении на Perl

Сотни тысяч строк Perl кода

Сайт, бэкофис, много скриптов

Регистрация IDN доменов на разных языках.

Page 3: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

Чтобы работать с текстом на разных языках одновременно.

to unicode or not to unicode

3

Page 4: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

Чтобы работать с текстом на разных языках одновременно.

to unicode or not to unicode

Даже для одного языка - однобайтные кодировки - не вариант

4

Page 5: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

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 это

Page 6: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

Текстовые строкиВнутренний

форматКак интерпретируются Как

интерпретируется 0xD0 0xAF

С флагом UTF-8

(Unicode)

Строка считается последовательностью

unicode символов, закодированных в UTF-8

Один символ "Я" (unicode U+042F)

Без флага UTF-8

Каждый байт - один символ

Два символа с кодами (U+00D0 U+00AF )

6

Page 7: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

Сделать так чтобы один и тот код работал со строками в разных форматах (unicode или cp1251)

Работаем одновременно в разных кодировках

В зависимости от конфига, приложение сможет работать то в одной кодировке то в другой

7

"Старый" код будет совместим только с режимом работы в формате cp1251

Page 8: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

sub func {my ($s) = @_; # $s либо cp1251 либо unicodeto_unicode($s); # теперь $s - точно unicode$s =~ s/(\W+)/_/g; # текстовая операцияfrom_unicode($s); # $s в том формате что и былоreturn $s;

}

Работаем одновременно в разных кодировках

8

Как выглядит такой код

Page 9: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

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

Page 10: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

sub func {my ($s) = @_; # $s либо cp1251 либо unicode

# to_unicode($s) - ничего не делает!$s =~ s/(\W+)/_/g; # текстовая операция

# from_unicode($s) - ничего не делает!return $s;

}

Работаем одновременно в разных кодировках

10

Как этот код работает в режиме Unicode

Page 11: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

Работаем одновременно в разных кодировках

11

Режим to_unicode from_unicode

CP1251 CP1251 -> UNICODE

UNICODE -> CP1251

Unicode NOP NOP

Page 12: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

Работаем одновременно в разных кодировках

12

Режим to_unicode from_unicode to_cp1251 from_cp1251

CP1251 CP1251 -> UNICODE

UNICODE -> CP1251

NOP NOP

Unicode NOP NOP UNICODE -> CP1251

CP1251 -> UNICODE

Page 13: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

$value =~ /Привет/i # исходник в CP1251

Что ещё нужно сделать с кодом

13

Строковые константы

use utf8;$value =~ /Привет/i; # исходник в UTF-8

Было

Стало

Page 14: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

Что ещё нужно сделать с кодом

14

Расширенное толкование метасимволов регэкспов

Теперь это тоже \d

Page 15: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

Что ещё нужно сделать с кодом

15

Ввод-вывод

to_unicode($str);open my $fh, ">:encoding(UTF-8)", $filename;print $fh $str;

Page 16: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

Тестирование

16

package MyClass;use utf8;sub myfunc {

my ($x, $data) = @_;do_something($data);if ($x == 42) {

do_even_more($data);$s =~ s/Ё/Е/g;

}}

Page 17: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

Тестирование

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;

}}

Page 18: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

Test::Spec

18

Тестирование

Test::Spec::Mocks

$myobj->expects('do_something')->with("Привет")->returns("Тест");

Page 19: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

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">

Page 20: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

Перекодировать шаблоны

20

Template Toolkit

my $provider = Template->new({ ENCODING => 'utf8',});

Page 21: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

SET NAMES 'cp1251' SET NAMES 'utf8'

21

DBI, DBD::mysql

Page 22: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

Только байты. Никакого текста.

22

Redis, Redis::Fast

Perl не может отличить байты от текста

Используем сериализацию. Например Storable.только сериализация которая восстанавливает все скаляры в оригинальном виде

Page 23: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

Почта

23

Другие большие подсистемы

Логи

Что-то ещё.. Индивидуальный подход к каждой.

Page 24: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

sha256("привет") - не определено!

24

Пароли

sha256(utf8("привет")) <> sha256(cp1251("привет"))

Page 25: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

Бизнес-логика - потом

25

Бизнес-логика

Проверяем что входные данные - валидируются

Page 26: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

26

Сложные структуры данныхmy $dataref = +{

x => [1,2,3,"тест"],y => { a => 42 },

};to_unicode_recursive($dataref);

Page 27: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

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;

}

Page 28: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

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;

}

Page 29: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

29

Сложные структуры данныхmy $dataref = +{

x => [1,2,3,"тест"],y => { a => 42 },z => bless { field => "привет"}, 'MyObject'

};to_unicode_recursive($dataref); # ошибка

Page 30: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

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

Page 31: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

В общем Redis сервере кэшируются фрагменты html в разных кодировках

31

Запуск на production

Веб приложение пишет в базу символы, которых нет в cp1251, значит cp1251 процессы их “не увидят”

Page 32: виктор ефимов «Unicode в perl и как перевести на него систему» (yapc  russia 2014, спб)

Написание возможно в 2 строкиПлашку регулировать по длине текста

Вывод или посыл зрителюСпасибо!Буду рад ответитьна ваши вопросы!

E-mail:[email protected]

32