Как я могу рассматривать аргументы командной строки как UTF-8 в Perl?

Как мне относиться к элементам @ARGV как UTF-8 в Perl?

В настоящее время я использую следующий обходной путь..

use Encode qw(decode encode);

my $foo = $ARGV[0];
$foo = decode("utf-8", $foo);

.. который работает, но не очень элегантно.

Я использую Perl v5.8.8, который вызывается из bash v3.2.25 с LANG, установленным в en_US.UTF-8.

5 ответов

Решение

Внешние источники данных хитры в Perl. Для аргументов командной строки вы, вероятно, получаете их в виде кодировки, указанной в вашей локали. Не надейтесь, что ваш язык будет таким же, как у кого-то другого, кто может запустить вашу программу.

Вы должны выяснить, что это, а затем преобразовать во внутренний формат Perl. К счастью, это не так сложно.

Модуль I18N:: Langinfo содержит материал, необходимый для получения кодировки:

    use I18N::Langinfo qw(langinfo CODESET);
    my $codeset = langinfo(CODESET);

Когда вы знаете кодировку, вы можете декодировать их в строки Perl:

    use Encode qw(decode);
    @ARGV = map { decode $codeset, $_ } @ARGV;

Хотя Perl кодирует внутренние строки как UTF-8, вы никогда не должны думать об этом или знать об этом. Вы просто декодируете все, что получаете, что превращает это во внутреннее представление Perl для вас. Поверьте, что Perl справится со всем остальным. Когда вам нужно сохранить данные, убедитесь, что вы используете ту кодировку, которая вам нравится.

Если вы знаете, что ваша установка UTF-8, и терминал выдаст вам аргументы командной строки как UTF-8, вы можете использовать A вариант с Perl's -C переключатель. Это говорит вашей программе, что аргументы должны быть закодированы как UTF-8:

% perl -CA program

Вы также получите это просто -C, который включает несколько других опций Unicode:

% perl -C program

Я нахожу "если вы знаете" большой красный флаг, который на самом деле означает "мы не уверены".

Используйте Encode::Locale:

use Encode::Locale;
use Encode;

@ARGV = map { decode(locale => $_, 1) } @ARGV;

Это работает, также на Win32, довольно хорошо для меня.

То, как вы это сделали, кажется правильным. Это то, что я бы сделал.

Тем не менее, эта страница perldoc предполагает, что флаг командной строки -CA должен сказать это лечить @ARGV как utf-8. (не испытано).

Например для Windows установить код

chcp 1251

в perl:

use utf8;
use Modern::Perl;
use Encode::Locale qw(decode_argv);

 if (-t)
{
    binmode(STDIN, ":encoding(console_in)");
    binmode(STDOUT, ":encoding(console_out)");
    binmode(STDERR, ":encoding(console_out)");
}

Encode::Locale::decode_argv();

в командной строке

perl -C ppixregexplain.pl qr/\bмама\b/i > ex1.html 2>&1  

где ppixregexplain.pl

Вам не нужно делать ничего особенного с этой строкой. Строки Perl находятся в UTF-8 по умолчанию, начиная с Perl 5.8.

perl -CO -le 'print "\x{2603}"' | xargs perl -le 'print "I saw @ARGV"'

Приведенный выше код прекрасно работает на Ubuntu 9.04, OS X 10.6 и FreeBSD 7.

FalseVinylShrub поднимает хороший вопрос, мы можем увидеть определенную разницу между

perl -Mutf8 -wle ';print utf8::is_utf8($ARGV[0]) ? "t" : "f"' a

а также

perl -Mutf8 -CA -wle ';print utf8::is_utf8($ARGV[0]) ? "t" : "f"' a
Другие вопросы по тегам