PerlからUTF-8を出力するにはどうすればよいですか?


110

「utf8」プラグマを使用してPerlスクリプトを記述しようとしていますが、予期しない結果が発生しています。Mac OS X 10.5(Leopard)を使用しており、TextMateで編集しています。エディターとオペレーティングシステムの両方の設定はすべて、デフォルトでutf-8形式でファイルを書き込むようになっています。

しかし、以下をテキストファイルに入力し、「。pl」として保存して実行すると、ASCII以外の文字の代わりにわかりやすい「疑問符の付いたひし形」が表示されます。

#!/usr/bin/env perl -w

use strict;
use utf8;

my $str = 'Çirçös';
print( "$str\n" );

私が間違っていることは何か考えていますか?出力に「Çirçös」が表示されることを期待していますが、代わりに「 ir s」が表示されます。


1
たぶん、そのプログラムではない..私は出力を行い、あなたのエディタオーデルそのシェルを考える
n00ki3

すべての答えは、それを明示的にUTF8に設定する方法の質問に正しく答えます。stackoverflow.com/a/14405949/498634に示すように、端末のロケール設定に調整する必要があると思います。端末がUTF8に設定されておらず、UTF8でSTDOUTに書き込まれたデータが正しくエンコードされない可能性があります。
DanielBöhmer19年

操作方法についてのすばらしい回答utf8
Eugen Konkov

回答:


160

use utf8;Unicode 出力を有効にしません-プログラムでUnicodeを入力できます。これをプログラムのprint()ステートメントの前に追加します。

binmode(STDOUT, ":utf8");

それが役立つかどうかを確認します。STDOUT通常のASCIIではなくUTF-8で出力する必要があります。


私はこれについて知りませんでした(私はデータベースにUTF8を入れているだけで、印刷していません)。+1。
ポールトンブリン

1
どういたしまして。別の正解もご覧ください:stackoverflow.com/questions/627661/writing-perl-code-in-utf8/…そして覚えておいてください、TMTOWTDI。そして、@ Paul-UTF-8をファイルに書き込む場合は、おそらくそのファイルハンドルでbinmode()を使用して「適切な」UTF-8にする必要がありますが、それが機能する場合は..
Chris Lutz

1
他の方法:オープンプラグマ(search.cpan.org/perldoc/open)、-Cスイッチ(perldoc.perl.org/perlrun.html#-C
ysth

1
ここでFWIWが理由です。utf8に多かれ少なかれ保存されているにもかかわらず、latin1(ISO-8859-1)文字のみを含む文字列は、デフォルトでlatin1として出力されます。このように、Unicode対応のPerlを使用しても、Unicode以前の時代のスクリプトは同じように機能します。
mirod

3
utf8プラグマでは、ソースをUNICODEで記述できません。これにより、重要な違いであるUNICODEのUTF-8(またはUTF-EBCDIC)エンコーディングでソースを強制的に理解できます。
Chas。オーエンス

83

openプラグマを使用できます。

たとえば 以下は、STDOUT、STDIN、およびSTDERRがUTF-8を使用するように設定します。

use open qw/:std :utf8/;

1
ところで...私はあなたに+1を与えました。この状況では、おそらくbinmode(STDOUT、 ':utf8')の方が正しいと思います。「use open」には他にも良い使い方がありますが、STDOUTのみをエンコードするように設定する方法を見つけられないようです。
draegtun 2009年

66

TMTOWTDIは、作業方法に最適な方法を選択しました。私は環境法を使っているので、考える必要はありません。

では環境

export PERL_UNICODE=SDL

上のコマンドライン

perl -CSDL -le 'print "\x{1815}"';

またはbinmodeで

binmode(STDOUT, ":utf8");          #treat as if it is UTF-8
binmode(STDIN, ":encoding(utf8)"); #actually check if it is UTF-8

またはPerlIOで

open my $fh, ">:utf8", $filename
    or die "could not open $filename: $!\n";

open my $fh, "<:encoding(utf-8)", $filename
    or die "could not open $filename: $!\n";

またはopenプラグマで

use open ":encoding(utf8)";
use open IN => ":encoding(utf8)", OUT => ":utf8";

1
包括的な回答の+1。ノートSDLの両方暗示さ-CPERL_UNICODE。のuse open ':locale'それはのインスクリプト同等であるため、プラグマは、また、言及する価値がある-Cexport PER_UNICODE=。これらの3つのいずれでも、環境のロケールがUTF8ベースであると想定して、すべての入力および出力ストリーム(ファイルまたはstdin / stdout / stderr)にUTF8サポートを提供します。最後に、ソースコードもUTF8として扱うには、use utf8;プラグマを使用します。
mklement0 2014年

perl -Mutf8 -CSDL -e '...'/出力UTF-8を消費することを可能にするだけでなく内部として使用UTF-8リテラル-e貧乏人の場合フォルダの例を:perl -Mutf8 -CASDL -pe 'y/āáǎàēéěèīíǐìōóǒòūúǔùǖǘǚǜĀÁǍÀĒÉĚÈĪÍǏÌŌÓǑÒŪÚǓÙǕǗǙǛ/aaaaeeeeiiiioooouuuuüüüüAAAAEEEEIIIIOOOOUUUUÜÜÜÜ/'
vladr


0

おかげで、コード全体にutf8 :: encodeを含めないようにするための解決策がついに得られました。utf8でファイルを読み書きするなど、他のケースで合成して完了するため、またutf8でYAMLファイルのLoadFileと連携して動作します。

use utf8;
use open ':encoding(utf8)';
binmode(STDOUT, ":utf8");

open(FH, ">test.txt"); 
print FH "something éá";

use YAML qw(LoadFile Dump);
my $PUBS = LoadFile("cache.yaml");
my $f = "2917";
my $ref = $PUBS->{$f};
print "$f \"".$ref->{name}."\" ". $ref->{primary_uri}." ";

ここで、cache.yamlは次のとおりです。

---
2917:
  id: 2917
  name: Semanário
  primary_uri: 2917.xml

-3

シェルで行う:$ env | grep LANG

これはおそらく、シェルがutf-8ロケールを使用していないことを示しています。


実際には、utf-8に設定されていました。問題は、binmodeをutf-8に設定せずにSTDOUTに出力していたことです。

2
これは直交する問題です。端末エミュレータがデータを解釈する方法について心配する前に、正しいデータを出力するためのPerlスクリプトが必要です。
jrockway 2009年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.