2010-03-13 8 views
5

Mam zmienną środowiskową ustawioną w systemie Windows jako TEST=abc£, która używa strony kodowej Windows-1252. Teraz, kiedy uruchamiam program Perl test.pl, ta wartość środowiska przychodzi prawidłowo.Jak poprawnie używać zmiennych środowiskowych zakodowanych jako Windows-1251 w Perlu?

Kiedy zadzwonić inny kod Perl - test2.pl z test1.pl albo system(..) lub Win32::Process, środowisko pochodzi zniekształcone.

Czy ktoś może podać informacje, dlaczego tak się stało i jak go rozwiązać?

Wersja perl Używam jest 5.8.

Jeśli moje zrozumienie jest prawo, perl wewnętrznie używa utf-8, więc początkowy proces - test1.pl otrzymał ją bezpośrednio z Windows-1252utf-8. Kiedy wywołujemy inny proces, czy powinniśmy dokonać konwersji z powrotem na stronę kodową Windows-1252?

+0

Będziesz otrzymywać odpowiedzi znacznie szybciej, jeśli podasz minimalny kod, który pokazuje problem. Jeśli po prostu opisujesz to słowami, pozostaje wiele do wyobraźni i zamieszania. – daxim

+0

Jak to się stało, że żadna z tuzina odpowiedzi, które otrzymałeś na sześć pytań, które zadałeś, była wystarczająco dobra, aby zostać zaakceptowanym? –

+0

Tak, zrobiłem to teraz. – Kartlee

Odpowiedz

8

Nie ma to nic wspólnego z wewnętrznym kodowaniem ciągów Perla, ale z koniecznością odpowiedniego odkodowania danych pochodzących z zewnątrz. Dostarczę przypadek testowy. To jest Strawberry Perl 5.10 na zachodnioeuropejskim 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; 

Wykonanie:

> set TEST=abc£ 
> B:\sperl\perl\bin\perl.exe B:\test1.pl 

wyjścia (skrócony)

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}"] 

Jesteś ukąszony przez fakt, że Windows używa innego kodowania dla środowiska tekstowego (IBM850) niż dla środowiska graficznego (Windows-1252). Ekspert musi wyjaśnić głębsze szczegóły tego zjawiska.

EDIT:

Możliwe jest heurystycznie (czyli nie będzie można zrobić dobry uczynek czasami, szczególnie dla takich krótkich ciągów) określenia kodowania. Najlepsze rozwiązanie ogólnego zastosowania to Encode::Detect/Encode::Detect::Detector, oparte na Mozilla nsUniversalDetector.

Istnieje kilka sposobów dekodowania danych zewnętrznych, takich jak open pragma/IO layers i -C switch, ale dotyczą one tylko strumieni plików i programów. W tej chwili ze środowiska musi być wyraźnie zdekodowana. W każdym razie i tak to lubię, explicite pokazuje programistę konserwacji, o którym myślałeś topic.

+0

Dzięki daxim za odpowiedź. Kilka pytań - 1) Czy możliwe jest ustalenie, jakie kodowanie jest stosowane do ciągów pochodzących ze świata zewnętrznego? Pomoże to odpowiednio rozszyfrować w perlu. 2) Czy istnieje sposób instruowania perla, aby poradził sobie z wewnętrzną częścią dekodowania, zamiast robić to samodzielnie, określając kodowanie używane w zewnętrznym świecie? -Kartlee – Kartlee

+0

Dzięki za przypomnienie. Zrobiłem to teraz, co uważam za dopuszczalne. – Kartlee

Powiązane problemy