Come posso produrre UTF-8 da Perl?


110

Sto cercando di scrivere uno script Perl usando il pragma "utf8" e ottengo risultati inaspettati. Sto usando Mac OS X 10.5 (Leopard) e sto modificando con TextMate. Tutte le mie impostazioni sia per il mio editor che per il sistema operativo sono predefinite per scrivere file in formato utf-8.

Tuttavia, quando inserisco quanto segue in un file di testo, lo salvo come ".pl" e lo eseguo, ottengo il simpatico "rombo con un punto interrogativo" al posto dei caratteri non ASCII.

#!/usr/bin/env perl -w

use strict;
use utf8;

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

Hai idea di cosa sto sbagliando? Mi aspetto di ottenere 'Çirçös' nell'output, ma invece ottengo ' ir s'.


1
Forse non è il programma .. penso che sia la tua shell o il tuo editor che esegue l'output
— n00ki3

Tutte le risposte rispondono correttamente alla tua domanda su come impostarlo esplicitamente su UTF8. Penso che dovresti regolare le impostazioni locali del tuo terminale come mostrato in stackoverflow.com/a/14405949/498634 . Il terminale potrebbe non essere impostato su UTF8 e quindi i dati scritti su STDOUT in UTF8 verranno codificati in modo errato !
— Daniel Böhmer

Ottima risposta su come lavorare con utf8:
— Eugen Konkov

Risposte:


160

use utf8;non abilita l' output Unicode - ti permette di digitare Unicode nel tuo programma. Aggiungi questo al programma, prima della tua print()dichiarazione:

binmode(STDOUT, ":utf8");

Vedi se questo aiuta. Questo dovrebbe produrre STDOUToutput in UTF-8 invece che in ASCII ordinario.


Non lo sapevo (ho solo inserito UTF8 in un database, mai stampato). +1.
— Paul Tomblin

1
Prego. Vedere anche un'altra risposta corretta: stackoverflow.com/questions/627661/writing-perl-code-in-utf8/... e ricordare, TMTOWTDI. E @Paul - se stai scrivendo UTF-8 su un file, dovresti probabilmente usare binmode () su quel filehandle e renderlo "corretto" UTF-8, ma se funziona ..
— Chris Lutz

1
altri modi: il pragma aperto ( search.cpan.org/perldoc/open ), l'interruttore -C ( perldoc.perl.org/perlrun.html#-C )
— ysth

1
FWIW qui è il motivo: le stringhe che contengono solo caratteri latin1 (ISO-8859-1), nonostante siano memorizzate più o meno in utf8, verranno emesse come latin1 per impostazione predefinita. In questo modo gli script di un'era pre-unicode funzionano ancora allo stesso modo, anche con un perl compatibile con unicode.
— mirod

3
Il pragma utf8 non ti consente di scrivere la tua fonte in UNICODE, costringe a capire la tua fonte nella codifica UTF-8 (o UTF-EBCDIC) di UNICODE, una distinzione importante.
— Chas. Owens

83

Puoi usare il pragma aperto .

Per es. sotto imposta STDOUT, STDIN e STDERR per usare UTF-8 ....

use open qw/:std :utf8/;

1
BTW ... ti ho dato +1. Penso che binmode (STDOUT, ': utf8') sia probabilmente più corretto in questa situazione. "use open" ha altri buoni usi ma non riesco a trovare come puoi impostarlo per codificare solo STDOUT?
— draegtun

66

TMTOWTDI , ha scelto il metodo che meglio si adatta al tuo lavoro. Uso il metodo ambientale quindi non devo pensarci.

In ambiente :

export PERL_UNICODE=SDL

sulla riga di comando :

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

o con binmode :

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

o con 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";

o con il pragma aperto :

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

1
+1 per una risposta esauriente; nota che SDLè implicito sia con -Cche PERL_UNICODE. Il use open ':locale'pragma è anche degno di nota, perché è l'equivalente in-script di -Ce export PER_UNICODE=. Ognuno di questi 3 fornirà il supporto UTF8 per tutti i flussi di input e output (file o stdin / stdout / stderr), assumendo che la locale del tuo ambiente sia basata su UTF8. Infine, per trattare anche il codice sorgente come UTF8, usa il use utf8;pragma.
— mklement0

perl -Mutf8 -CSDL -e '...'consente di consumare / produrre UTF-8 e utilizzare i valori letterali UTF-8 all'interno, -ead esempio, per la cartella dei casi di un povero:perl -Mutf8 -CASDL -pe 'y/āáǎàēéěèīíǐìōóǒòūúǔùǖǘǚǜĀÁǍÀĒÉĚÈĪÍǏÌŌÓǑÒŪÚǓÙǕǗǙǛ/aaaaeeeeiiiioooouuuuüüüüAAAAEEEEIIIIOOOOUUUUÜÜÜÜ/'
— vladr


0

Grazie, finalmente ho una soluzione per non mettere utf8 :: encode in tutto il codice. Per sintetizzare e completare per altri casi, come scrivere e leggere file in utf8 e funziona anche con LoadFile di un file YAML in 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}." ";

dove cache.yaml è:

---
2917:
  id: 2917
  name: Semanário
  primary_uri: 2917.xml

-3

fai nella tua shell: $ env | grep LANG

Questo probabilmente mostrerà che la tua shell non sta usando una locale utf-8.


In realtà, era impostato su utf-8. Il problema era che stavo eseguendo l'output su STDOUT senza impostare binmode su utf-8;

2
Questa sarebbe una preoccupazione ortogonale. Hai bisogno del tuo script Perl per produrre dati corretti prima di poterti preoccupare di come il tuo emulatore di terminale li interpreta.
— jrockway
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.