'useutf8;'の使用 「印刷物のワイド文字」を教えてくれます


86

次のPerlプログラムを実行すると:

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

この警告が表示されます:

Wide character in print at -e line 1.

このPerlプログラムを実行すると:

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

警告は出ません。

use utf8PerlスクリプトでUTF-8文字を使用する必要があると思いました。なぜこれが機能しないのですか?どうすれば修正できますか?私はPerl5.16.2を使用しています。これがコマンドラインのワンライナーではなくファイルにある場合も、同じ問題が発生します。


3
「なぜこれが機能しないのですか?」それ機能しますが、Unicodeでの私の経験では、機能しているように見える非常に壊れたプログラムがたくさんあります。1つの問題を修正して、コードの誤りを少し少なくすると、結果ははるかに悪くなります。すべてが再び良く見えるのは、最後の部分を修正したときだけです。
hobbs 2013年

回答:


110

なし use utf8Perlがと、文字列は1バイト文字のシーケンスとして解釈されます。これからわか​​るように、文字列には4バイトがあります。

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

最初の3バイトは文字を構成し、最後の1バイトは改行です。

への呼び出し printこれらの4文字をSTDOUT送信します。次に、コンソールはこれらの文字を表示する方法を決定します。コンソールがUTF8を使用するように設定されている場合、コンソールはそれらの3バイトを単一の文字として解釈し、それが表示されます。

utf8モジュールを追加すると、状況が異なります。この場合、Perlは文字列を2文字として解釈します。

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

デフォルトでは、PerlのIOレイヤーはシングルバイト文字で動作していると想定しています。したがって、マルチバイト文字を印刷しようとすると、Perlは何かが間違っていると判断し、警告を出します。相変わらず、を含めることで、このエラーの詳細な説明を得ることができますuse diagnostics。それはこれを言うでしょう:

(S utf8)Perlは、予期していなかったときにワイド文字(> 255)に遭遇しました。この警告は、I / O(印刷など)ではデフォルトでオンになっています。この警告を静める最も簡単な方法は、出力に:utf8レイヤーを追加することです(例:binmode STDOUT、 ':utf8')。警告をオフにする別の方法は、警告を追加しないことです 'utf8'; しかし、それはしばしば不正行為に近いです。一般に、ファイルハンドルをエンコーディングで明示的にマークすることになっています。openおよびperlfunc / binmodeを参照してください。

他の人が指摘しているように、マルチバイト出力を受け入れるようにPerlに指示する必要があります。これを行うには多くの方法があります(いくつかの例については、Perl Unicodeチュートリアルを参照してください)。最も簡単な方法の1つは、-CSコマンドラインフラグを使用することです。これは、3つの標準ファイルハンドル(STDIN、STDOUT、およびSTDERR)にUTF8を処理するように指示します。

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

vs

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

Unicodeは大きくて複雑な領域です。これまで見てきたように、多くの単純なプログラムは正しいことをしているように見えますが、理由は間違っています。プログラムの一部を修正し始めると、すべてのプログラムを修正するまで状況が悪化することがよくあります。


-Mutf81つのライナーperlにない場合のスペル方法は?
レイヤン

@LeiYang:use utf8;
Dave Cross

80

すべてのuse utf8;ソースコードがUTF-8を使用してエンコードされたPerlを教えてくれているん。テキストのエンコード方法をPerlに指示する必要があります。

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

おかげで、これは、@ DaveCrossの回答がカバーするコマンドラインのワンライナーとは対照的に、ファイルに保存されたプログラムに対してうまく機能します。
vktec 2016年

19

すべての標準出力をUTF-8としてエンコードします。

binmode STDOUT, ":utf8";

2
use open ':std', ':encoding(UTF-8)';別の回答で提案されているように、これはSTDOUTに対しても実行されますが、STDERRおよびSTDINもUTF-8としてマークされるため、1つのステートメントの価格で3つ取得できます。stackoverflow.com/a/42194059
Stephen Ostermiller

同意します。これはさらに良いです。
ボリス・イワノフ

14

CPANモジュールを使用すると、「どこでもutf8を実行する」に近づくことができますutf8::all

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

ときprint、それは(ない255より大きい文字印刷できないことを何か受ける:encoding層が提供されていないが)、それはあなたがUTF-8を使用して、それをエンコードするためのものを想定しています。問題について警告した後、そうします。



0

スペイン語では、使用を開始する以外にこのエラーを見つけることができます。

use utf8;

エディターのエンコーディングは別のエンコーディングです。したがって、エディターに表示されるのは、Perlが行うことではありません。このエラーを解決するには、エディターのエンコードをUnicode / UTF-8に変更するだけです。


1
いいえ。これがエラーの原因ではありません。コードはすべてUTF8として適切にエンコードされていましたが、出力ファイルハンドルはそれが正しいことを認識していませんでした。
デイブクロス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.