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

Nikolay Mishin mi на ya.ru
Вт Сен 23 12:51:49 PDT 2014


Здравствуйте, Илья
добавил 
$lang = decode(locale => $lang);
удалив все лишнее, вы просто супер!!
https://github.com/mishin/presentation/blob/master/100_regex_4_moscow_pm.pl
а код модуля говорит сам за себя

 if ($^O eq "MSWin32") {
        unless ($ENCODING_LOCALE) {
            # Try to obtain what the Windows ANSI code page is
            eval {
                unless (defined &GetACP) {
                    require Win32::API;
                    Win32::API->Import('kernel32', 'int GetACP()');
                };
                if (defined &GetACP) {
                    my $cp = GetACP();
                    $ENCODING_LOCALE = "cp$cp" if $cp;
                }
            };
        }




23.09.2014, 13:15, "Илья Винокуров" <ilvin на mail.ru>:
> Здравствуйте, Николай!
>
> Вы используете Console::Locale.
> Почитайте документацию https://metacpan.org/pod/Encode::Locale
> Из нее вы поймете, что этот модуль определяет кодировку консоли
> более точно, чем детекторы.
>
> Если для STDIN, STDERR, STDOUT вы сделали телодвижения по
> автоматической перекодировке, то для @ARGV ничего не сделано,
> поэтому разумно использовать:
>
> my $lang = decode(locale => $ARGV[0]);
>
> А детекторы кодировок - это зло, существующее из-за безнадеги...
>
> С почтением,
>   Илья Винокуров.
>
> Mon, 22 Sep 2014 23:58:07 +0400 от Nikolay Mishin <mi на ya.ru>:
>
>> Илья, привет , удалил Text::Iconv
>> -my $converter = Text::Iconv->new( "cp1251", "utf-8");
>> -$lang = $converter->convert($lang);
>> +Encode::from_to($lang, 'windows-1251', 'utf-8');
>> https://github.com/mishin/presentation/commit/2d1ba8adcfc451d45454490b5bf442f95bd41e0a
>> и все заработало,
>> правда получается, что кодировка , которую Encode::Detect::Detector
>> определяет как ISO-8859-7 является одновременно и кодировкой windows-1251,
>> странно, что больше этого нигде не написано, в общем парадоксальное решение,
>> чисто перебором
>>
>> 22.09.2014, 12:51, "Илья Винокуров" <ilvin на mail.ru>:
>>>  Здравствуйте, Николай.
>>>
>>>  Внутри Perl строки хранятся в кодировке, совместимой с UTF-8. Эта кодировка называется utf8.
>>>  Когда строки вводятся в Perl, их нужно декодировать из различных кодировок в utf8.
>>>  В том числе нужно декодировать UTF-8 в utf8.
>>>  Если строку нужно вывести из Perl, то эту строку нужно кодировать в различные кодировки.
>>>  В том числе нужно кодировать utf8 в UTF-8
>>>
>>>  Этим занимаются функции 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