'Use utf8;' kullanımı bana 'baskıda geniş karakter' veriyor


86

Aşağıdaki Perl programını çalıştırırsam:

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

Bu uyarıyı alıyorum:

Wide character in print at -e line 1.

Bu Perl programını çalıştırırsam:

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

Bir uyarı almıyorum.

use utf8Bir Perl komut dosyasında UTF-8 karakterlerini kullanmam gerektiğini düşündüm . Bu neden çalışmıyor ve bunu nasıl düzeltebilirim? Perl 5.16.2 kullanıyorum. Komut satırında tek bir satır olmak yerine bir dosyadaysa aynı sorunu yaşıyorum.


3
"Bu neden çalışmıyor?" O does işi, ama çok kırık bir sürü program olduğunu orada olduğu Unicode ile benim deneyim oldu bakmak onlar gibi çalışıyoruz. Bir şeyi düzelttiğinizde, kodu biraz daha az yanlış yaptığınızda, sonuçlar çok daha kötü görünür. Sadece son kısmı düzelttiğinizde her şey tekrar iyi görünüyor.
hobbs

Yanıtlar:


110

use utf8Perl olmadan , dizenizi tek baytlık karakterler dizisi olarak yorumlar. Bundan da görebileceğiniz gibi dizenizde dört bayt vardır:

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

İlk üç bayt karakterinizi oluşturur, sonuncusu satır beslemesidir.

Çağrı, printbu dört karakteri STDOUT'a gönderir. Konsolunuz daha sonra bu karakterlerin nasıl görüntüleneceğini hesaplar. Konsolunuz UTF8 kullanacak şekilde ayarlanmışsa, bu üç baytı tek karakteriniz olarak yorumlayacaktır ve görüntülenen budur.

utf8Modüle eklersek , işler farklıdır. Bu durumda Perl, dizenizi sadece iki karakter olarak yorumlar.

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

Varsayılan olarak, Perl'in GÇ katmanı tek baytlık karakterlerle çalıştığını varsayar. Bu yüzden çok baytlı bir karakter yazdırmaya çalıştığınızda Perl bir şeylerin yanlış olduğunu düşünür ve sizi uyarır. Her zamanki gibi, ekleyerek bu hata için daha fazla açıklama alabilirsiniz use diagnostics. Bunu söyleyecek:

(S utf8) Perl, beklemediği bir zamanda geniş bir karakterle (> 255) karşılaştı. Bu uyarı varsayılan olarak G / Ç için açıktır (yazdırma gibi). Bu uyarıyı susturmanın en kolay yolu çıktıya: utf8 katmanını eklemektir, örneğin binmode STDOUT, ': utf8'. Uyarıyı kapatmanın bir başka yolu da uyarı eklememektir 'utf8'; ama bu genellikle hile yapmaya daha yakındır. Genel olarak, dosya tanıtıcısını bir kodlama ile açıkça işaretlemeniz gerekir, bkz. Open ve perlfunc / binmode.

Diğerlerinin de belirttiği gibi, Perl'e çok baytlı çıktıyı kabul etmesini söylemeniz gerekir. Bunu yapmanın birçok yolu vardır ( bazı örnekler için Perl Unicode Eğitimine bakın). En basit yollardan biri -CS, üç standart dosya tanıtıcısına (STDIN, STDOUT ve STDERR) UTF8 ile ilgilenmesini söyleyen komut satırı bayrağını kullanmaktır .

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

vs

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

Unicode, büyük ve karmaşık bir alandır. Gördüğünüz gibi, birçok basit program doğru şeyi yapıyor gibi görünüyor, ancak yanlış nedenlerle. Programın düzeltme kısmına başladığınızda size giderdikten kadar, işler çoğu zaman kötüye gidecek tüm programın.


-Mutf8Tek satırlık perl'de değilse nasıl hecelenir?
Lei Yang

@LeiYang:use utf8;
Dave Cross

80

Tek use utf8;yaptığı Perl'e kaynak kodunun UTF-8 kullanılarak kodlandığını söylemektir. Perl'e metninizi nasıl kodlayacağını söylemeniz gerekir:

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

Teşekkürler, bu, @ DaveCross'un cevabının kapsadığı komut satırındaki tek satırlık programların aksine, dosyalarda depolanan programlar için iyi çalışıyor.
vktec

19

Tüm standart çıktıları UTF-8 olarak kodlayın:

binmode STDOUT, ":utf8";

2
use open ':std', ':encoding(UTF-8)';başka bir yanıtın önerdiği gibi bunu STDOUT için yapar ama aynı zamanda STDERR ve STDIN'i UTF-8 olarak işaretler, böylece bir ifadenin fiyatı için üç tane alırsınız. Ayrıca bkz. Stackoverflow.com/a/42194059
Stephen Ostermiller

Katılıyorum. Bu daha da iyi.
Boris Ivanov

14

CPAN modülünü kullanarak "sadece utf8'i her yerde yapın" seçeneğine yaklaşabilirsiniz utf8::all.

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

Ne zaman print(hayır zaman 255 daha büyük karakter yazdırmak olamayacağını şey aldığında :encodingkatman sağlanır), bu UTF-8 kullanarak kodlamak içindir varsayar. Sorun hakkında uyardıktan sonra bunu yapar.



0

İspanyolca'da, kullanmaya başlamanın yanında bu hatayı bulabilirsiniz:

use utf8;

Editör kodlamanız farklı bir kodlamada. Yani editörde gördüğünüz şey Perl'in yaptığı şey değildir. Bu hatayı çözmek için editör kodlamasını Unicode / UTF-8 olarak değiştirin .


1
Hayır. Hataya neden olan bu değil. Kodun tamamı UTF8 olarak doğru bir şekilde kodlanmıştı, ancak çıktı dosya tanıtıcısı bunun olduğunu bilmiyordu.
Dave Cross
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.