LINUX.ORG.RU

Проблема с кодировками: аргумент командной строки и переменная кодируются по-разному?

 ,


1

2

Если передаю perl-скрипту параметр - слово кириллицей, то функция, которая использует этот параметр для поиска, не отрабатывает правильно. Если объявляю внутри скрипта переменную, равную той же строке, которую раньше передавал в качестве параметра и получал shift'ом - всё работает.

Изначально у меня скрипт запускался #!/usr/bin/perl -CS и юзал модуль utf8 («use utf8;»), но я попытался поиграться с этим, убирая то одно, то другое - это ничего не даёт. Всё равно полученное из комадной строки и записанное в теле скрипта на уровне байтовом - совершенно разные значения.

Как избавиться от этой «кириллической» проблемы?

★★★★★
Ответ на: комментарий от Eshkin_kot

Ага, спасибо... Работает! :)

Но! Если указать -CSDA, то печатает белиберду вместо кириллицы, а если -CDA, то при use warnings постоянно говорит про wide characters. Как сделать так, чтобы perl перестал быть недовольным выводом wide characters, при этом не отключая warnings'ы совсем?

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от joy4eg

Не-а, либо warning'и, либо нет warning'ов, но печатается белиберда. Пока просто отключил warning'и - проблем никаких, кроме того, что какую-то важную проблему в коде могу пропустить из-за этого.

DRVTiny ★★★★★
() автор топика

Зачем такой use utf8; Всегда пишу так и в utf-8 локале всё работает.

vitus@s1:~/devel/projects/perl$ cat find_perl.pl 
#!/usr/bin/perl -w
use strict;
my $rt="Аргумент";
print "Великий $rt=$ARGV[0]\n";
opendir (DIR, ".") or die $!;
while (my $file = readdir(DIR)) {
        print "$file\n" if ($ARGV[0] eq $file);
}
print `find . -iname "$ARGV[0]" -print`;
vitus@s1:~/devel/projects/perl$ ./find_perl.pl файл.txt
Великий Аргумент=файл.txt
файл.txt
./файл.txt

vtVitus ★★★★★
()
Последнее исправление: vtVitus (всего исправлений: 2)
Ответ на: комментарий от vtVitus

Зачем такой use utf8; Всегда пишу так и в utf-8 локале всё работает.

потому что у Вас не строки, а байты, length($rt) у Вас = 16, а не 8.

Eshkin_kot ★★
()
Ответ на: комментарий от redgremlin
use feature qw(say);
use open qw(:std :utf8);
use utf8;
utf8::decode($ARGV[0]);
say $ARGV[0];
$test = 'тест';
say 'same' if $test eq $ARGV[0];


perl test.pl тест
тест
same

redgremlin ★★★★★
()
Ответ на: комментарий от Eshkin_kot

У меня дома на Linux Mint'е почему-то тоже нормально выполняется тот кусок кода, который на работе выполняется с warnings'ами по поводу широких символов. Чудные дела твои, Господи. Может, это бага какая-то именно в используемой мной версии Perl'а. Я как завтра на работу приду, попробую ваш кусок кода запустить: он у меня дома тоже отлично работает.

DRVTiny ★★★★★
() автор топика

Перед работой с текстом его нужно декодировать:

use Encode::Locale;
use Encode qw(encode decode);

my $characters = decode locale => $bytes;

При чтении текста из файла можно воспользоваться IOLayer'ом:

binmode $read_filehandle, ":decode(locale)";

Вместо автоматического определения кодировки её можно указать вручную (заменить locale на koi8-r в примерах выше, например).

Теперь если попытаться напечатать $characters, они напечатаются в UTF-8 и будет выведен warning «wide characters in ...». Это потому, что символы перед вводом/выводом нужно закодировать обратно в байты:

$new_bytes = encode locale => $characters;

binmode $write_filehandle, ":encode(locale)";

Для текста в UTF-8 можно использовать специальный IOLayer ":utf8", он работает быстрее, потому что внутри Perl символы хранятся в utf-8 и для их печати достаточно снять флаг «characters» со строки. Для декодирования его тоже можно использовать, если уверены, что вход - 100% валидный UTF-8.

(См. также: perldoc Encode::Locale о локалях console_in и console_out; perldoc perlunitut).

AITap ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.