Uso di "use utf8;" mi dà "Carattere ampio in stampa"


86

Se eseguo il seguente programma Perl:

perl -e 'use utf8; print "鸡\n";'

Ottengo questo avviso:

Wide character in print at -e line 1.

Se eseguo questo programma Perl:

perl -e 'print "鸡\n";'

Non ricevo alcun avviso.

Pensavo use utf8fosse necessario utilizzare i caratteri UTF-8 in uno script Perl. Perché questo non funziona e come posso risolverlo? Sto usando Perl 5.16.2. Ho lo stesso problema se questo è in un file invece di essere un rivestimento sulla riga di comando.


3
"Perché non funziona?" Si fa il lavoro, ma è stata la mia esperienza con Unicode che ci sono un sacco di programmi molto rotti là fuori che guardare come stanno lavorando. Quando aggiusti una cosa, rendendo il codice leggermente meno sbagliato, i risultati sembrano molto peggiori. È solo quando aggiusti l' ultima parte che tutto sembra di nuovo a posto.
hobbs

Risposte:


110

Senza use utf8Perl interpreta la tua stringa come una sequenza di caratteri a byte singolo. Ci sono quattro byte nella tua stringa come puoi vedere da questo:

$ perl -E 'say join ":", map { ord } split //, "鸡\n";'
233:184:161:10

I primi tre byte compongono il tuo personaggio, l'ultimo è il line-feed.

La chiamata a printinvia questi quattro caratteri a STDOUT. La tua console quindi risolverà come visualizzare questi caratteri. Se la tua console è impostata per utilizzare UTF8, interpreterà quei tre byte come un singolo carattere e questo è ciò che viene visualizzato.

Se aggiungiamo nel utf8modulo, le cose sono diverse. In questo caso, Perl interpreta la tua stringa come solo due caratteri.

$ perl -Mutf8 -E 'say join ":", map { ord } split //, "鸡\n";'
40481:10

Per impostazione predefinita, il livello IO di Perl presume che funzioni con caratteri a byte singolo. Quindi, quando provi a stampare un carattere multibyte, Perl pensa che qualcosa non va e ti dà un avvertimento. Come sempre, puoi ottenere ulteriori spiegazioni per questo errore includendo use diagnostics. Dirà questo:

(S utf8) Perl ha incontrato un carattere wide (> 255) quando non se ne aspettava uno. Questo avviso è attivo per impostazione predefinita per I / O (come la stampa). Il modo più semplice per silenziare questo avviso è semplicemente aggiungere il livello: utf8 all'output, ad esempio binmode STDOUT, ': utf8'. Un altro modo per disattivare l'avviso consiste nell'aggiungere nessun avviso "utf8"; ma questo è spesso più vicino a barare. In generale, dovresti contrassegnare esplicitamente il filehandle con una codifica, vedi open e perlfunc / binmode.

Come altri hanno sottolineato, devi dire a Perl di accettare output multibyte. Ci sono molti modi per farlo (vedere il Tutorial Perl Unicode per alcuni esempi). Uno dei modi più semplici è usare il -CSflag della riga di comando, che dice ai tre filehandle standard (STDIN, STDOUT e STDERR) di gestire UTF8.

$ perl -Mutf8 -e 'print "鸡\n";'
Wide character in print at -e line 1.
鸡

vs

$ perl -Mutf8 -CS -e 'print "鸡\n";'

Unicode è un'area grande e complessa. Come hai visto, molti programmi semplici sembrano fare la cosa giusta, ma per le ragioni sbagliate. Quando inizi a riparare una parte del programma, le cose spesso peggiorano finché non avrai risolto tutto il programma.


Come si scrive -Mutf8se non in un perl di rivestimento?
Lei Yang,

@LeiYang:use utf8;
Dave Cross,

80

Tutto quello che use utf8;fa è dire a Perl che il codice sorgente è codificato usando UTF-8. Devi dire a Perl come codificare il tuo testo:

use open ':std', ':encoding(UTF-8)';

Grazie, questo funziona bene per i programmi archiviati in file, al contrario di una riga di comando sulla riga di comando, che copre la risposta di @ DaveCross.
vktec

19

Codifica tutto lo standard output come UTF-8:

binmode STDOUT, ":utf8";

2
use open ':std', ':encoding(UTF-8)';come proposto da un'altra risposta fa questo per STDOUT ma contrassegna anche STDERR e STDIN come UTF-8, quindi ne ottieni tre al prezzo di un'istruzione. Vedi anche stackoverflow.com/a/42194059
Stephen Ostermiller

Essere d'accordo. Questo è anche meglio.
Boris Ivanov,

14

Puoi avvicinarti a "fai utf8 ovunque" usando il modulo CPAN utf8::all.

perl -Mutf8::all -e 'print "鸡\n";'

Quando printriceve qualcosa che non può stampare (carattere più grande di 255 quando non :encodingviene fornito alcun livello), si presume che intendessi codificarlo usando UTF-8. Lo fa, dopo aver avvertito del problema.



0

In spagnolo puoi trovare questo errore quando accanto a iniziare a usare:

use utf8;

La codifica del tuo editor è in una codifica diversa. Quindi quello che vedi nell'editor non è quello che fa Perl. Per risolvere questo errore basta cambiare la codifica dell'editor in Unicode / UTF-8 .


1
No. Non è questo che ha causato l'errore. Il codice era tutto correttamente codificato come UTF8 ma il filehandle di output non sapeva che lo fosse.
Dave Cross
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.