[Moscow.pm] кодировка в Perl почему все это так странно работает?

Victor Efimov victor на vsespb.ru
Вт Сен 23 02:19:49 PDT 2014


23 сентября 2014 г., 12:48 пользователь Илья Винокуров <ilvin на mail.ru> написал:
> Здравствуйте, Виктор.
>
> Терминология действительно сильно упрощенная, так как
> внутреннее представление строки Perl проще назвать еще одной кодировкой,
> с которой нужно работать, чем копаться в кишках.

Не согласен. Термин "кодировка" к этому нельзя применять. Когда речь
идёт о кодировке - речь идёт о бинарных данных (байтах).
Символы же это не байлы - это элементы, код у которых может быть
больше 255. Так же в Perl чётко идеологически разграничены операции
над текстом и над бинарными данными.
А именно есть операции которые думают что их операнды текст (регэкспы,
вывод в файл у которго стоит binmode encoding), есть операции которые
думают что их операнды - байты (вывод в файл где нет binmode encoding,
функции типа pack). Это всё нельзя уложить в концепцию кодировок.

символы vs байты определены здесь
http://search.cpan.org/~shay/perl-5.20.1/pod/perlunitut.pod#Text_strings_%28character_strings%29

>
> Вот попробуй человеку объяснить зачем нужно для строки в UTF-8 кодировке
> делать Encode::decode('UTF-8', $string). А когда говоришь, что у Perl своя
> кодировка,
> так сразу человек начинает правильно перекодировать строки... А без этой
> абстракции человек лезет флаги строкам устанавливать...

Может новичку это поможет на ранней стадии только потом помешает.
Если бы концепция про кодировки была верная, можно было бы
конвертировать между кодировками с помощью Encode::from_to,
и вообще не понятно API когда делаются две функции
Encode::decode/encode чтобы конвертировать из/в кодировку.

>
> И такой ход мыслей у многих людей, так что здесь
> http://search.cpan.org/~shay/perl-5.20.1/pod/perlunifaq.pod#What%27s_the_difference_between_UTF-8_and_utf8?
> Плюнули и согласились:
> Okay, if you insist: the "internal format" is utf8, not UTF-8.


Не согласен с интерпретацией этого куска документации.
На самом деле речь там идёт про что:

1) Есть кодировка "UTF-8" и "utf8". Когда декодируют первую, принимают
во внимание то что не все Unicode символы существуют в прикоде. Когда
декодируют вторую, это игнорируется,
т.е. вторая используется как "кодек" похожий на UTF-8 для произвольных
(бинарных !) данных а не текста.

2) Внутрненний формат строки в perl, когда у ней установлен UTF-8
флаг, является не строгим вариантом UTF-8, т.е. в ней могут
содержаться вообще не символы, просто набор чисел закодированных в
кодек UTF8, не являющийся валидным UTF-8 но с точки зрения перл
полностью валидным.

например perl -e 'print v100.2000.3000'

v100.2000.3000 - это строка из трёх элементов: 100, 2000 и 3000.
закодированна этим кодеком. без оглядки на то есть ли в стандарте
unicode эти символы. так можно закодировать произвольные числа. т.е.
UTF8
как бы используется perl не по назначению.

именно поэтому написан этот параграф.



>
> С почтением,
>   Илья Винокуров.
>
>
> Mon, 22 Sep 2014 12:58:13 +0400 от Victor Efimov <victor на vsespb.ru>:
>
> 22 сентября 2014 г., 12:51 пользователь Илья Винокуров <ilvin на mail.ru>
> написал:
>> Здравствуйте, Николай.
>>
>> Внутри Perl строки хранятся в кодировке, совместимой с UTF-8. Эта
>> кодировка
>> называется utf8.
>> Когда строки вводятся в Perl, их нужно декодировать из различных кодировок
>> в
>> utf8.
>> В том числе нужно декодировать UTF-8 в utf8.
>> Если строку нужно вывести из Perl, то эту строку нужно кодировать в
>> различные кодировки.
>> В том числе нужно кодировать utf8 в UTF-8
>>
>
> только тут введена какя-то странная терминология, которой на самом деле нет.
>
> В perl строки не храянятся как набор абстрактных символов. Рассуждения
> про их кодировку лучше присекать на корню.
> Отличия между utf8 и UTF-8 - вовсе не в этом, а в том что utf-8 более
> строкая валидация чем utf8.
>
> Но в остальном, если в тексте выше заменить "utf8" на "символьная
> строка", то будет ок.
>
>> Этим занимаются функции Encode::encode('UTF-8', $string) и
>> Encode::decode('UTF-8', $string).
>>
>> Text::Iconv - не используйте это, если точно не знаете почему вам нужен
>> именно этот модуль.
>>
>> Концепцию работы с кодировками в Perl я рассказал,
>> а вот свой скрипт поправить потрудитесь сами пожалуйста...
>>
>> PS: Чтобы не возиться в явном виде с перекодированием строк, в перл
>> используют
>>
>> binmode STDIN, ":encoding(console_in)" if -t STDIN;
>> binmode STDOUT, ":encoding(console_out)" if -t STDOUT;
>> binmode STDERR, ":encoding(console_out)" if -t STDERR;
>>
>> После этого в STDIN/STDOUT можно читать/писать строки в кодировке utf8 без
>> перекодирования...
>>
>> С почтением,
>> Илья Винокуров.
>>
>> Mon, 22 Sep 2014 01:28:15 +0400 от Nikolay Mishin <mi на ya.ru>:
>>
>> Привет, MoscowPM,
>> тут родился вопрос под win7 (юникс могут быть теже странности, не
>> проверял)
>>
>> #!/usr/bin/env perl
>> use utf8;
>> use Modern::Perl;
>> use Encode::Locale;
>> use Encode qw( decode encode from_to);
>> use Text::Iconv;
>> use Encode::Detect::Detector;
>> use Data::Dumper qw( Dumper );
>>
>>
>> if (-t)
>> {
>> binmode(STDIN, ":encoding(console_in)");
>> binmode(STDOUT, ":encoding(console_out)");
>> binmode(STDERR, ":encoding(console_out)");
>> }
>>
>> my $lang = shift or die "Usage: $0 What_is_your_language?\n";
>> my_dump('lang_01',$lang);
>> my $converter = Text::Iconv->new( "cp1251", "utf-8");
>> $lang = $converter->convert($lang);
>> my_dump('lang_02',$lang);
>> $lang = Encode::decode("utf8",$lang);
>> my_dump('lang_03',$lang);
>> my_dump('lang_04_перл',qq{перл});
>>
>> $lang =~ /(perl|перл) (?{print "use Perl or die!!\nИспользуй Перл или
>> умри!!";}) /ix;#русский не мачится, почему?
>>
>> sub my_dump
>> {
>> my ($name,$var)=@_;
>> local $Data::Dumper::Useqq = 1;
>> local $Data::Dumper::Indent = 0;
>> local $Data::Dumper::Terse = 1;
>> print(Encode::Detect::Detector::detect(qq{$lang})." ".qq{\$$name }."
>> dump=".Dumper($var)."\n");
>> }
>>
>> этот же код на гитхабе
>>
>> https://github.com/mishin/presentation/blob/master/100_regex_4_moscow_pm.pl
>>
>> моя задача была, чтобы скрипт
>> perl 100_regex_4_moscow_pm.pl перл
>> читая из консоли слово "перл" находил его в регексе внутри скрипта
>>
>> вопросы:
>> 1) почему, если в консоле
>> perl -MEncode::Detect::Detector -E "say
>> Encode::Detect::Detector::detect(qq{перл})"
>> у меня кодировка ISO-8859-7
>> my $converter = Text::Iconv->new( "cp1251", "utf-8");
>> Text::Iconv ее проглатывает как cp1251 (причем ISO там не проходит) ?
>>
>> 2)что происходит со строкой здесь
>> UTF-8 $lang_02 dump="\320\277\320\265\321\200\320\273"
>> $lang = Encode::decode("utf8",$lang);
>> UTF-8 $lang_03 dump="\x{43f}\x{435}\x{440}\x{43b}"
>> --что такое делает decode?
>> я так понимаю - он починивает utf8, но что конкретно
>>
>> спасибо, хорошей недели!!
>>
>>
>> --
>> С уважением
>> Николай Мишин
>>
>> --
>> Moscow.pm mailing list
>> moscow-pm на pm.org | http://moscow.pm.org
>>
>>
>>
>> --
>> Moscow.pm mailing list
>> moscow-pm на pm.org | http://moscow.pm.org
>>
> --
> Moscow.pm mailing list
> moscow-pm на pm.org | http://moscow.pm.org
>
>
>
> --
> Moscow.pm mailing list
> moscow-pm на pm.org | http://moscow.pm.org
>


Подробная информация о списке рассылки Moscow-pm