web-dev-qa-db-ja.com

Perlでの文字列のエンコーディングをどのように推測できますか?

Unicode文字列があり、そのエンコーディングが何であるかわかりません。この文字列がPerlプログラムによって読み取られるとき、Perlが使用するデフォルトのエンコーディングはありますか?もしそうなら、どうすればそれが何であるかを知ることができますか?

入力から非ASCII文字を削除しようとしています。私はそれを行ういくつかのフォーラムでこれを見つけました:

my $line = encode('ascii', normalize('KD', $myutf), sub {$_[0] = ''});

入力エンコーディングが指定されていない場合、上記はどのように機能しますか?次のように指定する必要がありますか?

my $line = encode('ascii', normalize('KD', decode($myutf, 'input-encoding'), sub {$_[0] = ''});
25
Maulin

未知のものがどのエンコーディングで使用されているかを見つけるには、試してみるだけです。モジュール Encode :: Detect および Encode :: Guess それを自動化します。 (Encode :: Detectのコンパイルに問題がある場合は、そのフォークを試してください Encode :: Detective 代わりに。)

use Encode::Detect::Detector;
my $unknown = "\x{54}\x{68}\x{69}\x{73}\x{20}\x{79}\x{65}\x{61}\x{72}\x{20}".
              "\x{49}\x{20}\x{77}\x{65}\x{6e}\x{74}\x{20}\x{74}\x{6f}\x{20}".
              "\x{b1}\x{b1}\x{be}\x{a9}\x{20}\x{50}\x{65}\x{72}\x{6c}\x{20}".
              "\x{77}\x{6f}\x{72}\x{6b}\x{73}\x{68}\x{6f}\x{70}\x{2e}";
my $encoding_name = Encode::Detect::Detector::detect($unknown);
print $encoding_name; # gb18030

use Encode;
my $string = decode($encoding_name, $unknown);

encode 'ascii'は、非ASCII文字を取り除くための不完全な解決策です。すべてが質問マークに置き換えられます。これは損失が大きすぎて役に立ちません。

# Bad example; don't do this.
use utf8;
use Encode;
my $string = 'This year I went to 北京 Perl workshop.';
print encode('ascii', $string); # This year I went to ?? Perl workshop.

読みやすいASCIIテキストが必要な場合は、代わりに Text :: Unicodecode をお勧めします。これも不可逆エンコーディングですが、プレーンなencode上記。

use utf8;
use Text::Unidecode;
my $string = 'This year I went to 北京 Perl workshop.';
print unidecode($string); # This year I went to Bei Jing  Perl workshop.

ただし、支援できる場合は、これらの不可逆エンコーディングを避けてください。後で操作を元に戻したい場合は、PERLQQまたはXMLCREFのいずれかを選択してください。

use utf8;
use Encode qw(encode PERLQQ XMLCREF);
my $string = 'This year I went to 北京 Perl workshop.';
print encode('ascii', $string, PERLQQ);  # This year I went to \x{5317}\x{4eac} Perl workshop.
print encode('ascii', $string, XMLCREF); # This year I went to 北京 Perl workshop.
32
daxim

Encode モジュールには、これを実行する方法があります。 decodeは、エンコーディングと思われる生のオクテットです。オクテットが有効なエンコーディングを表していない場合、オクテットは爆発し、evalでキャッチします。それ以外の場合は、適切にエンコードされた文字列が返されます。例えば:

 use Encode;

 my $a_with_ring =
   eval { decode( 'UTF-8', "\x6b\xc5", Encode::FB_CROAK ) }
     or die "Could not decode string: $@";

これには、同じオクテットシーケンスが複数のエンコーディングで有効になる可能性があるという欠点があります。

これについては、次の Effective Perl Programming、2nd Edition で詳しく説明します。これには、Unicodeの取り扱いに関する章全体が含まれています。でも全部投稿したら出版社は怒るだろうと思います。 :)

JuerdのUnicodeアドバイス 、およびPerlに付属しているUnicodeドキュメントのいくつかもご覧ください。

4
brian d foy