2009-03-09 18 views
92

Próbuję napisać skrypt Perla za pomocą "utf8" pragma i otrzymuję nieoczekiwane wyniki. Używam Mac OS X 10.5 (Leopard) i edytuję TextMate. Wszystkie moje ustawienia dla mojego edytora i systemu operacyjnego są domyślnie zapisywane w formacie utf-8.Jak mogę wyprowadzić UTF-8 z Perla?

Po wprowadzeniu do pliku tekstowego, zapisaniu go jako ".pl", i wykonaniu go, otrzymuję przyjazny "diament ze znakiem zapytania" zamiast znaków spoza ASCII.

#!/usr/bin/env perl -w 

use strict; 
use utf8; 

my $str = 'Çirçös'; 
print("$str\n"); 

Każdy pomysł, co robię źle? Oczekuję, że w wynikach pojawi się "Çirçös", ale zamiast tego otrzymuję " ir s".

+1

Może to nie jest program .. myślę, że to twoja skorupa lub edytor, który robi wyjście – n00ki3

Odpowiedz

141

use utf8; nie włącza Unicode wyjście - pozwala na wpisanie Unicode w swoim programie. Dodaj to do programu, zanim twoje print() oświadczenie:

binmode(STDOUT, ":utf8"); 

Sprawdź, czy to pomaga. To powinno spowodować, że wyjście STDOUT będzie w UTF-8 zamiast zwykłego ASCII.

+0

Nie wiedziałem o tym (umieszczałem UTF8 w bazie danych, nigdy go nie drukując). +1. –

+0

To zadziałało, Chris. Dziękuję Ci! –

+1

Nie ma za co. Zobacz także inną poprawną odpowiedź: http://stackoverflow.com/questions/627661/writing-perl-code-in-utf8/627975#627975 i zapamiętaj, TMTOWTDI. I @Paul - jeśli piszesz UTF-8 do pliku, powinieneś prawdopodobnie użyć binmode() na tym uchwycie pliku i uczynić go "właściwym" UTF-8, ale jeśli to działa .. –

-2

Przekieruj dane wyjściowe do pliku tekstowego i wypróbuj w edytorze. Jeśli wyświetla się dobrze, oznacza to awarię terminala.

+0

Nie, terminal Leopard ma domyślnie ustawiony LANG na "en_US.UTF-8". Po prostu domyślnie (dla kompatybilności wstecznej - blek) Perl wypisze znaki 128-255 jako? zamiast Unicode, chyba że wyraźnie powiesz, że nie. –

+0

Również niektóre edytory (np. Vim) automatycznie wykrywają, czy plik ma UTF-8, czy też nie, i stara się pokazać go poprawnie, niezależnie od kodowania. Otwarcie pliku w edytorze nie jest niezawodnym testem. (Również całkiem sporo edytorów faktycznie działa w - potencjalnie wadliwym - terminalu). Ponadto, biorąc dosłownie, odpowiada niepoprawnie na pytanie OP. –

-3

robić w powłoce: $ env | grep LANG

To prawdopodobnie pokaże, że powłoka nie używa UTF-8.

+0

W rzeczywistości został ustawiony na utf-8. Problem polegał na tym, że wysyłałem do STDOUT bez ustawiania trybu bin na utf-8; –

+2

To byłby problem ortogonalny. Potrzebujesz skryptu Perla, aby uzyskać poprawne dane wyjściowe , zanim będziesz mógł się martwić o to, jak interpretuje je twój emulator terminala. – jrockway

75

Możesz użyć open pragma.

Na przykład. poniżej ustawia STDOUT, STDERR STDIN & używać UTF-8 ....

use open qw/:std :utf8/; 
+1

Dobrze. Chciałbym dać +1, ale dzisiaj nie mogę głosować. –

+1

BTW ... Dałem u +1. Myślę, że binmode (STDOUT, ": utf8") jest prawdopodobnie bardziej poprawny w tej sytuacji. "use open" ma inne dobre zastosowania, ale nie mogę znaleźć sposobu, w jaki można go ustawić tylko do kodowania tylko STDOUT? – draegtun

57

TMTOWTDI, wybrał metodę, która najlepiej pasuje do sposobu pracy. Używam metody środowiska, więc nie muszę o tym myśleć.

W environment:

export PERL_UNICODE=SDL 

na command line:

perl -CSDL -le 'print "\x{1815}"'; 

lub binmode:

binmode(STDOUT, ":utf8");   #treat as if it is UTF-8 
binmode(STDIN, ":encoding(utf8)"); #actually check if it is UTF-8 

lub PerlIO:

open my $fh, ">:utf8", $filename 
    or die "could not open $filename: $!\n"; 

open my $fh, "<:encoding(utf-8)", $filename 
    or die "could not open $filename: $!\n"; 

lub z open pragma:

use open ":encoding(utf8)"; 
use open IN => ":encoding(utf8)", OUT => ":utf8"; 
+1

'-CSDL' pracował dla mnie, gdy' binmode' sam nie. – beerbajay

+1

+1 w celu uzyskania kompleksowej odpowiedzi; zauważ, że 'SDL' jest implikowane zarówno z' -C' i 'PERL_UNICODE'. Warto również wspomnieć o 'use open ': locale'' pragma, ponieważ jest to odpowiednik skryptu' -C' i 'export PER_UNICODE ='. Każdy z tych 3 daje wsparcie UTF8 dla wszystkich strumieni wejściowych i wyjściowych (bez względu na to, czy są to pliki, czy stdin/stdout/stderr), zakładając, że ustawienia narodowe twojego środowiska są oparte na UTF8. Wreszcie, aby traktować kod _source_ jako UTF8, użyj 'use utf8;' pragma. – mklement0

0

Dzięki, wreszcie rozwiązanie, aby nie umieszczać utf8 :: kodowanie całego kodu. do syntezy i kompletne dla innych przypadkach, jak zapisu i odczytu plików w UTF-8, a także współpracuje z loadFile z pliku YAML w utf8

use utf8; 
use open ':encoding(utf8)'; 
binmode(STDOUT, ":utf8"); 

open(FH, ">test.txt"); 
print FH "something éá"; 

use YAML qw(LoadFile Dump); 
my $PUBS = LoadFile("cache.yaml"); 
my $f = "2917"; 
my $ref = $PUBS->{$f}; 
print "$f \"".$ref->{name}."\" ". $ref->{primary_uri}." "; 

gdzie cache.yaml to:

--- 
2917: 
    id: 2917 
    name: Semanário 
    primary_uri: 2917.xml 
Powiązane problemy