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.
"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
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