Как получить правильные аргументы командной строки не ASCII в ActiveState Perl? - PullRequest
2 голосов
/ 19 октября 2011

Выполнение следующей команды

perl -e "for (my $i = 0; $i < length($ARGV[0]); $i++) {print ord(substr($ARGV[0], $i, 1)), qq{\n}; }" αβγδεζ

в окне Windows 7 cmd с ActiveState Perl v5.14.2 дает следующий результат:

97
223
63
100
101
63

Приведенные выше значения являются бессмысленнымиt соответствуют любой известной кодировке, поэтому попытка декодировать их с помощью подхода, рекомендованного в Как я могу трактовать аргументы командной строки как UTF-8 в Perl? не помогает.Изменение активной кодовой страницы окна команд не приводит к изменению результатов.

Ответы [ 4 ]

3 голосов
/ 19 октября 2011

Ваша система, как и любая другая система Windows, которую я знаю, по умолчанию использует кодовую страницу 1252 ANSI, поэтому вы можете попробовать использовать

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

Обратите внимание, что cp1252 не может представлять все эти символы, поэтому консоль и, следовательно, Perl фактически получают

  • 97
  • 223
  • ? 63
  • д 100
  • е 101
  • ? 63

Существует "широкий" интерфейс для передачи (почти) любой кодовой точки Unicode в программу, но

  1. Широкий интерфейс не используется при вводе команды в командной строке.
  2. Perl использует интерфейс ANSI для извлечения параметров, поэтому даже если вы запустили Perl с использованием широкого интерфейса, параметры будут понижены до ANSI, когда Perl их получит.

Извините, но это ситуация типа "вы не можете". Вам нужен другой подход. Диомидис Спинеллис предлагает изменить кодовую страницу ANSI вашей системы следующим образом в Win7:

  1. Панель управления
  2. Регион и язык
  3. Административные
  4. Язык для не-Unicode программ
  5. Установите Текущий язык для программ, не поддерживающих Юникод, на язык, связанный с конкретными символами (греческий в вашем случае).

На этом этапе вы будете использовать кодировку кодовой страницы ANSI, связанной с новой выбранной кодировкой, вместо cp1252 (cp1253 для греческого).

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

Обратите внимание, что использование chcp для изменения кодовой страницы, используемой в окне консоли, не влияет на кодовую страницу, в которой Perl получает свои аргументы, которая всегда является кодовой страницей ANSI. См. Примеры ниже (cp737 - греческая кодовая страница OEM , а cp1253 - греческая кодовая страница ANSI . Вы можете найти кодировки, помеченные как 37 и M7 в этом документе .)

C:\>chcp 737
Active code page: 737

C:\>echo αβγδεζ | od -t x1
0000000 98 99 9a 9b 9c 9d 20 0d 0a

C:\>perl -e "print map sprintf('%x ', ord($_)), split(//, $ARGV[0])" αβγδεζ
e1 e2 e3 e4 e5 e6

C:\>chcp 1253
Active code page: 1253

C:\>echo αβγδεζ | od -t x1
0000000 e1 e2 e3 e4 e5 e6 20 0d 0a

C:\>perl -e "print map sprintf('%x ', ord($_)), split(//, $ARGV[0])" αβγδεζ
e1 e2 e3 e4 e5 e6
0 голосов
/ 20 октября 2011

Вы можете попробовать использовать https://metacpan.org/pod/Win32::Unicode::Native. Он должен иметь то, что вам нужно.

0 голосов
/ 19 октября 2011

Если я помещаю символы в файл (из OS-X), копирую его в окно Windows (как file.txt), затем запускаю:

perl -CI -e "chomp($_=<STDIN>); map{print ord, qq{\n}} split(//)" < file.txt

Тогда я получаю ожидаемое:

946
947
948
949
950

Но если я скопирую содержимое file.txt в командную строку, я получу бред.

Как говорил @ikegami, я не думаю, что это можно сделать из командыстрока, поскольку у вас нет локали UTF-8.

0 голосов
/ 19 октября 2011

Это сработало для меня (на OS-X, но должно быть переносимым):

echo  αβγδεζ |perl -CI -e "chomp($in=<STDIN>);for (my $i = 0; $i < length($in); $i++) {print ord(substr($in, $i, 1)), qq{\n}; }"

Это было для STDIN; для ARGV:

perl -CA -e "for (my $i = 0; $i < length($ARGV[0]); $i++) {print ord(substr($ARGV[0], $i, 1)), qq{\n}; }" αβγδεζ

См. Параметр -C в perlrun: http://perldoc.perl.org/perlrun.html#Command-Switches

...