Мне установили переменную среды в Windows как TEST=abc£
который использует Windows-1252
кодовая страница. Теперь, когда я запускаю программу Perl test.pl
это значение среды прибывает правильно.
Когда я называю другой код Perl - test2.pl
от test1.pl
любой system(..)
или Win32::Process
, среда прибывает искаженная.
Кто-то может предоставить информацию, почему это могло быть и способ разрешить его?
Версия perl
Я использую, 5.8.
Если мое понимание является правильным, perl
внутренне использование utf-8
, так начальный процесс - test1.pl
полученный это прямо из Windows-1252
→ utf-8
. Когда мы назовем другой процесс, должны мы преобразовывать назад в Windows-1252
кодовая страница?
Это не имеет отношения к внутренней кодировке строк Perl, а связано с необходимостью правильно декодировать данные, поступающие извне. Я предоставлю тестовый пример. Это Strawberry Perl 5.10 на западноевропейской Windows XP.
test1.pl:
use Devel::Peek;
print Dump $ENV{TEST};
use Encode qw(decode);
my $var = decode 'Windows-1252', $ENV{TEST};
print Dump $var;
system "B:/sperl/perl/bin/perl.exe B:/test2.pl";
test2.pl:
use Devel::Peek;
print Dump $ENV{TEST};
use Encode qw(decode);
my $var = decode 'IBM850', $ENV{TEST};
# using Windows-1252 again is wrong here
print Dump $var;
Execute:
> set TEST=abc£
> B:\sperl\perl\bin\perl.exe B:\test1.pl
Output (shortened):
SV = PVMG(0x982314) at 0x989a24
FLAGS = (SMG, RMG, POK, pPOK)
PV = 0x98de0c "abc\243"\0
SV = PV(0x3d6a64) at 0x989b04
FLAGS = (PADMY, POK, pPOK, UTF8)
PV = 0x9b5be4 "abc\302\243"\0 [UTF8 "abc\x{a3}"]
SV = PVMG(0x982314) at 0x989a24
FLAGS = (SMG, RMG, POK, pPOK)
PV = 0x98de0c "abc\243"\0
SV = PV(0x3d6a4c) at 0x989b04
FLAGS = (PADMY, POK, pPOK, UTF8)
PV = 0x9b587c "abc\302\243"\0 [UTF8 "abc\x{a3}"]
Вы укушены тем, что Windows использует другую кодировку для текстовой среды (IBM850), чем для графической (Windows-1252). Эксперт должен объяснить более глубокие детали этого явления.
Edit:
Можно эвристически (то есть иногда это не даст нужного результата, особенно для таких коротких строк) определить кодировки. Лучшим решением общего назначения является Encode::Detect/Encode::Detect::Detector, который основан на Mozilla nsUniversalDetector.
Существуют некоторые способы неявного декодирования внешних данных, такие как open
pragma/IO layers и -C
switch, однако они работают только с файловыми потоками и аргументами программы. В настоящее время, из окружения должны быть декодированы явно. В любом случае, мне это больше нравится, явное показывает программисту, занимающемуся сопровождением, что вы продумали тему.