Как я могу рассматривать аргументы командной строки как 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.

Ответы

Ответ 1

Внешние источники данных сложны в 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 -C. Это говорит вашей программе, что аргументы кодируются как UTF-8:

% perl -CA program

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

% perl -C program

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

Ответ 2

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

use Encode::Locale;

decode_argv Encode::FB_CROAK;

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

Ответ 3

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

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

Ответ 4

Например, для окон set code

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

Ответ 5

Вам не нужно делать ничего особенного для строки. 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