2013-03-04 11 views
62

Se si esegue il seguente programma Perl:Uso di 'use utf8;' mi dà 'carattere largo in stampa'

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

ottengo questo avvertimento:

Wide character in print at -e line 1. 

Se corro questo programma Perl:

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

Non ricevo un avviso.

Pensavo che use utf8 fosse necessario per utilizzare caratteri UTF-8 in uno script Perl. Perché 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 solo liner sulla riga di comando.

+3

"Perché non funziona?" Funziona *, ma è stata la mia esperienza con Unicode che ci sono un sacco di programmi molto rotti là fuori che * sembrano * come se funzionassero. Quando risolvi una cosa, rendendo il codice leggermente meno sbagliato, i risultati sembrano molto peggiori. È solo quando aggiusti la * ultima * parte che tutto sembra di nuovo buono. – hobbs

+0

Di solito risolto impostando l'handle di output su 'binmode' con la codifica corretta ... http://albertech.blogspot.com/2017/04/fix-annoying-wide-character-in-print.html – jar

risposta

88

Senza use utf8 Perl interpreta la stringa come sequenza di caratteri a byte singolo. Ci sono quattro byte nella stringa, come si può vedere da questa:

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

I primi tre byte compongono il vostro personaggio, l'ultima è la line-feed.

La chiamata a print invia questi quattro caratteri a STDOUT. La tua console quindi funziona 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 il modulo utf8, le cose sono diverse. In questo caso, Perl interpreta la stringa come solo due caratteri.

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

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

(S utf8) Perl incontrato un carattere esteso (> 255), quando non si aspettava uno. Questo avviso è di default attivato per I/O (come la stampa). Il modo più semplice per evitare questo avviso è semplicemente aggiungere il livello: utf8 all'output , ad es. binmode STDOUT, ': utf8'. Un altro modo per disattivare l'avviso è di aggiungere nessun avviso 'utf8'; ma questo è spesso più vicino all'inganno . In generale, si suppone di contrassegnare esplicitamente il filehandle con una codifica, vedere open e perlfunc/binmode.

Come altri hanno sottolineato, è necessario dire a Perl di accettare l'uscita multi-byte. Ci sono molti modi per farlo (vedi lo Perl Unicode Tutorial per alcuni esempi). Uno dei modi più semplici è utilizzare il flag della riga di comando -CS, che indica i tre filehandle standard (STDIN, STDOUT e STDERR) per gestire UTF8.

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

vs

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

Unicode è una zona di grande e complesso. Come hai visto, molti programmi semplici sembrano fare la cosa giusta, ma per ragioni sbagliate. Quando inizi a correggere parte del programma, le cose andranno sempre peggio finché non avrai risolto nel del programma.

+0

Come si scrive '-Mutf8' se non in un liner perl? –

+0

@LeiYang: 'usa utf8;' –

60

Tutto use utf8; indica a Perl che il codice sorgente è codificato utilizzando UTF-8. È necessario dire a Perl come codificare il testo:

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

Grazie, questo funziona bene per i programmi memorizzati nei file, al contrario di one-liner sulla riga di comando, che copre la risposta di @DaveCross. – Samadi

11

è possibile avvicinarsi a "just do utf8 ovunque" utilizzando il modulo CPAN utf8::all.

Quando print riceve qualcosa che non si può stampare (carattere maggiore di 255 quando non viene fornito alcun :encoding strato), si assume che intendevi per codificare utilizzando UTF-8. Lo fa, dopo aver avvertito del problema.

12

Encode tutto l'output standard UTF-8:

binmode STDOUT, ":utf8"; 
3

È possibile utilizzare questo,

perl -CS filename. 

Sarà anche termina quell'errore.

1

In spagnolo si può trovare questo errore quando accanto di iniziare a utilizzare:

use utf8; 

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

+1

No. Questo non è ciò che causa l'errore. Il codice era tutto correttamente codificato come UTF8 ma il filehandle di output non sapeva che lo fosse. –

Problemi correlati