[Moscow.pm] unicode & regexp

Victor Efimov victor на vsespb.ru
Чт Май 22 06:34:04 PDT 2014


22 мая 2014 г., 17:24 пользователь Алексей Мышкин <parserpro на gmail.com> написал:
> Нормальный линуксовый терминал.

Я не говорю что он плохой, у меня он так же себя ведёт. Просто это его
поведение, а не perl.

> Я вот думаю что какой-то из байт может оказаться кодом волшебного символа
> для регекспа - тогда может произойти что угодно.

Вряд ли, все волшебные символы - ASCII. Все байты из которых состоит
UTF-8 код не-ASCII символа - не ASCII. Это свойство UTF-8
называется "совместимо с ASCII", иначе, например, в именах файлов в ФС
Linux, могли случайно оказаться байты "/" или всякие "*", но такого
быть не может.

Но может быть обратно - всякие волшебные символы \s \w \d будут
совпадать с байтами, которые под них не должны подпадать (perl в
данном случае считает что байты - это текст в latin1).
Диапазоны и [] в таком виде тоже "не работают". Много чего не работает.
Работать с UTF-8 данными в режиме не 'use utf8' (т.е. UTF-8 без флага)
- нельзя. Можно только чтото простое делать типа $s =~ /привет\d+/ при
этом это будет
без багов, только если точно знаешь что происходит во всех нюансах, а их много.

>
>
> 22 мая 2014 г., 17:11 пользователь Victor Efimov <victor на vsespb.ru> написал:
>
>> например:
>>
>> без use utf8, строка '№«».,' видится perl как отдельные байты.
>> никакого отношения к символам, которые ты написал, не имеющие.
>> какой-то символ может состоять из 2х и более байтов.
>> они считаются отдельными. строка получается
>> "\342\204\226\302\253\302\273.," (oct)
>> quotemeta над этой строкой просто эскейпит ascii точки.
>>
>> $str при этом "... \302\253\302\273\302\253\302\273" (в нём вместо 4х
>> кавычек 8 "символов")
>>
>> результирующая строка
>>
>> ". \302"
>>
>> что логично. точка 1 раз. пробел 1 раз. и символ \302 1 раз, т.к. все
>> не-ascii символы из исходной $str входят
>> в [] в регэкспе.
>>
>> далее выводим эту строку не на экран а в файл (сделав редирект ">")
>>
>> смотрим, получились байты 0x2E (точка) 0x20 (пробел) 0xC2 (это как раз
>> \302 oct)
>>
>> выводим на экран этот файл: cat file
>> если последний символ обрезался (точно так же как если изначально
>> запустить скрипт)- это проблемы твоего терминала.
>> он ждёт UTF8 , а тут какие-то левые байты, не являющиеся валидным UTF8
>> если к этой строке добавить ещё пару символов, будет нормально
>> выводиться (вернее будет выводиться ромбик - "неизвестный символ").
>>
>>
>> 22 мая 2014 г., 16:48 пользователь Victor Efimov <victor на vsespb.ru>
>> написал:
>> > Я думаю смогу объяснить подробно что и почему, про все нюансы. Но я же
>> > говорю - не понятно что должно происходить. Выводит в обоих случаях
>> > что-то непонятное.
>> >
>> > 22 мая 2014 г., 16:41 пользователь Алексей Мышкин <parserpro на gmail.com>
>> > написал:
>> >> Это не объяснение. Символ-то почему режется?
>> >> Ладно бы на "широкий символ" ругнулось - это понятно. Но почему строка
>> >> выводится не целиком - вот вопрос.
>> >>
>> >>
>> >> 22 мая 2014 г., 16:26 пользователь devrow на gmail.com <devrow на gmail.com>
>> >> написал:
>> >>
>> >>>
>> >>>
>> >>> http://stackoverflow.com/questions/6162484/why-does-modern-perl-avoid-utf-8-by-default/6163129#6163129
>> >>>
>> >>>
>> >>> On 22.05.2014 15:24, Алексей Мышкин wrote:
>> >>>>
>> >>>> А объяснить?
>> >>>>
>> >>>>
>> >>>> 22 мая 2014 г., 15:16 пользователь Antonio Nikishaev <a на lelf.me
>> >>>> <mailto:a на lelf.me>> написал:
>> >>>>
>> >>>>
>> >>>>
>> >>>>     On 22 May 2014, at 14:58, Алексей Мышкин <parserpro на gmail.com
>> >>>>     <mailto:parserpro на gmail.com>> wrote:
>> >>>>
>> >>>>      > Всем доброго дня.
>> >>>>      > Есть такой код:
>> >>>>      > #!/usr/bin/env perl
>> >>>>      > use strict;
>> >>>>      > #use utf8;
>> >>>>      >
>> >>>>      > my $BadChars = quotemeta '№«».,';
>> >>>>      >
>> >>>>      > my $BadCharsRX = qr/$BadChars/u;
>> >>>>      >
>> >>>>      > my $str = '... «»«»';
>> >>>>      >
>> >>>>      > $str =~ s/([$BadCharsRX])[$BadCharsRX]+/$1/g;
>> >>>>      >
>> >>>>      > print "$str\n";
>> >>>>      > =====cut=====
>> >>>>      >
>> >>>>      > выдаёт ахинею
>> >>>>      > если сделать так:
>> >>>>      >
>> >>>>      > my $str = '... №№№ «»«»';
>> >>>>      > то начинает работать.
>> >>>>      >
>> >>>>      > Что за чёрт?
>> >>>>      >
>> >>>>      > Perl v5.14.2
>> >>>>
>> >>>>     Писать надо нормально. Всё будет работать
>> >>>>
>> >>>>     use utf8;
>> >>>>     use open qw<:std :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