Добрый день, уважаемые.Подскажите пожалуйста почему Perl не парсит рег.выражения на русском вида [а-яА-Я] при использовании UTF8. Хотя с CP1251 проблем нет(если делаю iconv + использую setlocale(LC_CTYPE,"ru_RU.CP1251");
Имею:
$ locale
LANG=ru_RU.UTF-8
LC_CTYPE="ru_RU.UTF-8"
LC_NUMERIC="ru_RU.UTF-8"
LC_TIME="ru_RU.UTF-8"
LC_COLLATE="ru_RU.UTF-8"
LC_MONETARY="ru_RU.UTF-8"
LC_MESSAGES="ru_RU.UTF-8"
LC_PAPER="ru_RU.UTF-8"
LC_NAME="ru_RU.UTF-8"
LC_ADDRESS="ru_RU.UTF-8"
LC_TELEPHONE="ru_RU.UTF-8"
LC_MEASUREMENT="ru_RU.UTF-8"
LC_IDENTIFICATION="ru_RU.UTF-8"
LC_ALL=Файл, к-ый хочу пропарсить имеет строки вида:
"Администратор" "Марфа Васильевна"
Естественно он сохранен в UTF-8Мой скрипт:
#!/usr/bin/perluse strict;
use warnings;open(DATA,'file.txt');
my $infile = <DATA>;
close DATA;while($infile =~ m/([А-Яа-я]+)/gi) {
print "$1\n";
}На выходе получаю:
$ perl report.pl
Админи
а
о
Маа
Ва
ил
евнаВ чем трабла?
На википедии написано что с юникодом проблем не должно быть:
"Для использования последовательностей букв необходимо установить правильную кодовую страницу в которой эти последовательности будут идти в порядке от и до указанных символов. Для русского языка это Windows-1251, ISO 8859-5 и Юникод, так как в DOS-855, DOS-866 и KOI8-R русские буквы не идут одной целой группой или не упорядочены по алфавиту."
man perluniintro
man perlunifaq
man perlunitut
man perlunicode
Можно начать с попытки добавлять
use utf8;
use open ':encoding(utf8)';
utf8::upgrade($infile);
Если не получится, то придется таки читать.
>man perluniintro
>man perlunifaq
>man perlunitut
>man perlunicode
>Можно начать с попытки добавлять
>use utf8;
>use open ':encoding(utf8)';
>utf8::upgrade($infile);
>Если не получится, то придется таки читать.Добавил, теперь скрипт выглядит так:
$ less report.pl
#!/usr/bin/perluse utf8;
use open ':encoding(utf8)';
utf8::upgrade($infile);open(DATA,'file.txt');
my $infile = <DATA>;
close DATA;while($infile =~ m/([А-Яа-я]+)/gi) {
print "$1\n";
}$ less file.txt
"Администратор" "Марфа Васильевна"$ ./report.pl
Wide character in print at page.analyser_simplified.pl line 12.
Администратор
Wide character in print at page.analyser_simplified.pl line 12.
Марфа
Wide character in print at page.analyser_simplified.pl line 12.
ВасильевнаРаботает!! Спасибо. Осталось теперь тока разобраться с руганью про wide character.
завтра почитаю. спасибо.
Ну не все же одновременно надо было добавлять. Кроме того utf8::upgrade($infile); перед использованием my $infile вообще не имеет смысла. Используйте use strict дабы избегать таких ошибок.
Попробуйте такой вариант:
#!/usr/bin/perl -w
use strict;use utf8;
open(DATA,'file.txt');
my $infile = <DATA>;
utf8::decode($infile);
close DATA;while($infile =~ m/([А-Яа-я]+)/gi) {
my $s=$1;
#нельзя напрямую применять encode к $1 иначе получим бред после первой строки
utf8::encode($s);
print "$s\n";
}А вообще работа с юникодом в перле(да и в большинстве других языков) это шаманство, особенно когда много _различных_ потоков ввода/вывода.
>Мой скрипт:
>#!/usr/bin/perlВ какой кодировке файл скрипта сохранён?
И обычно во всех регекспах есть спецпоследовательность для обозначения любого набора букв. Что-то вроде [[:alnum:]] или \w, уж не знаю как в перле.
>И обычно во всех регекспах есть спецпоследовательность для обозначения любого набора букв.
>Что-то вроде [[:alnum:]] или \w, уж не знаю как в перле.Это по умолчанию только для английских, причем не только в перле. Кроме того в эти классы цифры тоже входят, а в \w еще и подчеркивание.
Перл позволяет работать с возможностями isalpha для локалей, в том числе и utf8, но для этого нужно явно указывать use locale.
>>И обычно во всех регекспах есть спецпоследовательность для обозначения любого набора букв.
>>Что-то вроде [[:alnum:]] или \w, уж не знаю как в перле.
>Это по умолчанию только для английских, причем не только в перле.В тикле под \w и [[:alpha:]] буквы из русской локали тоже подходят. Так что надо читать ман по конкретному языку.
В перле к строкам прикручены внутренние флаги, в частности есть флаг что строка во внутреннем формате, только с этим форматом нормально работают регулярные выражения и всякие там length и т.п.Большинство проблем с кодировками можно решить придерживаясь например такой схемы работы:
use utf8; # предписывает что константы и регулярные выражения, имеющие не-ASCII символы,
должны трактоваться как уникодные и приводиться ко внутреннему форматуuse Encode; # включаем модуль работы с кодировками.
$bytes = encode('utf-8', $string); # в байты, (из внутреннего формата)
$string = decode('utf-8', $bytes); # преобразовать во внутренний формат! ВАЖНО, если perl собран и операционная система настроена так, что внутреннее представление переменных в utf-8 и print'ы и прочее выводят в utf-8, то это не значит что не надо пропускать через decode( 'utf-8', ... ), строки пришедшие откуда-то (из socket'а или fcgi, или модуля какого-нибудь и т.п.) то что строка в utf-8 еще не значит что она во внутреннем формате.
При работе с файлами можно использовать специальный синтаксис при открытии:
open FH, "<:utf8", $filename; # подробнее "perldoc -f open"
>[оверквотинг удален]
> $bytes = encode('utf-8', $string); # в байты, (из внутреннего формата)
> $string = decode('utf-8', $bytes); # преобразовать во внутренний формат
> ! ВАЖНО, если perl собран и операционная система настроена так, что внутреннее
> представление переменных в utf-8 и print'ы и прочее выводят в utf-8,
> то это не значит что не надо пропускать через decode( 'utf-8',
> ... ), строки пришедшие откуда-то (из socket'а или fcgi, или модуля
> какого-нибудь и т.п.) то что строка в utf-8 еще не значит
> что она во внутреннем формате.
> При работе с файлами можно использовать специальный синтаксис при открытии:
> open FH, "<:utf8", $filename; # подробнее "perldoc -f open"Мне странно читать подобные недовольсва... некоторые абсолютно уверены, что это какая-то ошибка и потому не рабоате! Нет граждане непонимающие это не ошибка... И оно не должно работать Просто потому что всё это работает через ctype функции... А они не работают с мультибайтовыми кодировками! Ещё более странно даже не это, а то, что люди с таким упрорством пытаются использовать самую неудобную и самую тормознутую из всех кодировок utf8... Я не знаю ни одного приложения где такая кодировка действительно нужна. За исключением разве что языков с очень большим числом иероглифов как в китайском... Но мы же не китайцы!!! В большинстве приложений хватает ASCII кодировок и это разумно использовать именно их! Но если вам не хватает симоволв или надо одновременно более 2-х языков сразу(в вебе к примеру...) то используйте вы Unicode. Это на порядок проще и быстрее!!! И там всё рабоатет. Функции другие, н отак всё тоже самое... Открою вам секрет, UTF8 это не ASCII кодировка и не Unicode.. Это мудьтибайтовая кодировка... И отсюда все беды! Никогда её не используйте и у вас не будет проблем. Перекодировать строку из utf8 в любую другую очень прсото с помощью стандартной функции iconv.
- никаких проблем с использовнием utf8 в перл не возникает,
и в частности в связи с тем что кодировка мультибайтовая.- тормознутой кодировка быть не может, могут быть тормознутыми
алгоритмы (работающие с данными в разных кодировках).- на этапе обучения всегда бывают вопросы, здесь и есть их место.
- если есть данные о несоответствии поведения перл описанному
в документации пишите разработчикам перл.- "люди с таким упрорством пытаются использовать" - это вы видимо
про разработчиков таких систем как google yandex rambler и т.д.
А вы не пробовали задать другую локаль к примеру вызвав функцию setlocale? И у вас сразу всё станет настроено на другой язык и другую кодировку.. Так же легко перестроить среду с которой вы работаете, к примеру редактор, сообщения об ошибках и т.п. Да хоть всю систему если надо... Если у вас нет соотвствующей локализации для perl а ид программ, то их легко скачать с интернета и установить!!! Это же свободное ПО и там есть все мыслимые и немыслимые локализации!!! Ну в крайнем случае можете написать свою... Но нафига, если есть готовая!