perluniintro - Perl Unicode の手引き
このドキュメントは、Unicode の一般的な考えと、 Perl で Unicode をどのように使うかを書いています。
Unicode は、文字セットの標準です。 世界の全ての書記体系と、それに加えて、 他の多くのシンボルを体系化することを計画しています。
Unicode と、ISO/IEC 10646 は、よく調整された、コードポイントを提供する 標準です。 Unicode は、ほとんど全ての現代の文字セット標準、30 以上の書記体系と、 100 以上の言語を網羅します。 全ての商業的に重要な現代の言語を含みます。 もっとも大きい中国語、日本語、韓国語、それぞれの辞書の全ての文字もまた、 符号化されています。 この標準は、最終的には、250 の書記体系と、1000 以上の言語のほとんどすべての 文字を網羅する予定です。 Unicode 1.0 は、1991 年 10 月にリリースされ、Unicode 4.0 は、 2003 年 4 月にリリースされました。
Unicode の 文字 は、抽象的な存在です。 Unicode の文字は、どんな特定の整数幅にも、特に、C 言語の char
にも 束縛されません。 Unicode は、言語中立で、表示中立です: Unicode は、テキストの言語をエンコードしませんし、 フォントや他のグラフィカルなレイアウトの詳細を定義しません。 Unicode は、文字と、それらの文字からなるテキストを操作します。
Unicode は、LATIN CAPITAL LETTER A
や GREEK SMALL LETTER ALPHA
のような 文字と、その文字について固有の番号を定義します。 この場合は、それぞれ、0x0041 と、0x03B1 になります。 このような固有の番号は、コードポイント と呼ばれます。
Unicode 標準は、コードポイントに 16 進記法を使うのを好みます。 0x0041
のような番号に馴染みがなければ、後のセクション、 "Hexadecimal Notation" を覗いて見て下さい。 Unicode 標準は、U+0041 LATIN CAPITAL LETTER A
という表記を使って、 16 進法のコードポイントと標準的な文字の名前を書きます。
Unicode はまた、様々な文字の 性質 を定義します。 "大文字"、"小文字"、"10進数字"、"句読点" など; これらの性質は、文字の名前と独立です。 更に、様々な文字に対する操作、大文字化や小文字化や並び替えが 定義されています。
Unicode 文字は、1 つのコードポイントか、または、 (LATIN CAPITAL LETTER A
のような)、基本文字 に続いて、 1つ以上の(COMBINING ACUTE ACCENT
のような) 修飾語句 の、 どちらか一方から成っています。 この基本文字と修飾語句の順番は、combining character sequence と 呼ばれます。
これらの combining character sequence を "複数の文字" と呼ぶかどうかは、 考え方によります。 プログラマならば、おそらく、この順番のそれぞれの要素を、 1 つの単位か "文字" として、見ようとするでしょう。 全ての順番を一つの"文字"として見ることができます。 ですが、ユーザの考え方からは、おそらくユーザの言語の文脈でみえるような ものでしょう。
この、文字の"すべての順番"の見え方では、文字の総数には、制限がありません。 ですが、プログラマーの"一つの単位は一つの文字"という考え方では、"文字" の 概念は、より決定論的です。 このドキュメントでは、2 番目の考え方を取ります: 1 つの"文字"は、1 つの Unicode のコードポイントであり、それは、基本文字か、 combining character であるとします。
いくつかの組合せにとって、まだ構成されていない 文字があります。 たとえば、LATIN CAPITAL LETTER A WITH ACUTE
は、 単一のコードポイントとして定義されています。 しかし、これらの、まだ構成されていない文字は、いくつかの組合せで 可能でしかありません。 そして、それらは、主に、Unicode と、レガシー標準(ISO 8859 のような)との 間の相互変換をサポートすることを意味します。 一般的なケースでは、構成する方法はより広がります。 違った構成間の変換をサポートするために、表現を標準化する、様々な normalization forms もまた定義されています。
レガシーエンコーディングとの後方互換性のために、 "全ての文字に固有の番号" という考えは、少々壊れています: その代わりに、"少なくとも全ての文字に 1 つの番号" があります。 同じ文字が、いくつかのレガシーエンコーディングの中で、違うように 表現されていました。 逆は真でもなく: コードポイントには、文字が割り当てられていないものも あります。 1 番目に、使われているブロック内にもかかわらず、割り当てられていない コードポイントがあります。 2 番目に、特別な Unicode のコントロール文字があり、それらは、本物の文字を 表現しません。
Unicode について、よく知られている神話は、Unicode が、"16-ビット" である、 というものです。 Unicode は、0x0000
から、0xFFFF
までで、0x10000
(か、65536)の 文字を表現するだけ、というものです。 これは真実ではありません。 Unicode 2.0(1996 年 7 月)から、Unicode は、21ビット(0x10FFFF
)まで、 様々に定義されています。 Unicode 3.1(2001 年 3 月)から、文字は、0xFFFF
を超えて、定義されました。 最初の 0x10000
文字は、 Plane 0、または、Basime Multilingual Plane(BMP)と、と呼ばれました。 Unicode 3.1 で、全部で 17(そう、17)の Plane が定義されました -- ですが、 まだ、定義された全文字のどこにも、まだ近くにありません。
もう 1 つの神話は 256 文字ブロックが、何か言語を取り扱うことがある-- それぞれのブロックは言語か言語のセットで使われている文字を 定義するということです。 これもまた真実ではありません。 ブロックに分割されたものはありますが、それは、ほとんど完全に、 予想外のものです。 代わりに、scripts と呼ばれる、より有益なコンセプトがあります: Latin
script と、Greek
script と、その他のものがあります。 scripts は、ふつう、いくつかのブロックの変えられた部分を測っています。 詳しくは、Unicode::UCD を見て下さい。
Unicode のコードポイントは、抽象的な数字です。 この抽象的な数字を入出力するために、数字は、エンコードされる 必要が あるか、シリアライズされる か、どうか、しなければなりません。 Unicode は、複数の character encoding forms を定義していますが、 その中で、UTF-8 は、たぶん、もっとも有名です。 UTF-8 は、可変長のエンコーディングで、Unicode 文字を 1 から 6 バイト (現在定義されている文字では 4 バイトまでです)。 他のエンコーディングは、UTF-16 と UTF-32 と、それらの大小のエンディアンの 変形(UTF-8 は、バイトオーダーと独立です)を含みます。 ISO/IEC 10646 は、UCS-2 と UCS-4 の encoding forms を定義しています。
エンコーディングについて -- たとえば、surrogates と byte order marks(BOMs) -- もっと知りたければ perlunicode を 見て下さい。
Perl 5.6.0 から、Perl は、Unicode をネイティブに扱う能力を持っていました。 しかし、Perl 5.8.0 の最初の RC リリースは、重大な Unicode の仕事です。 メンテナンスリリースの 5.6.1 は、最初の Unicode 実装の多くの問題を 修正しました。 ですが、たとえば、5.6.1 で、Unicode での正規表現はまだ働きません。
Perl5.8.0 から、use utf8
の使用は、もはや必要ではありません。 初期のリリースでは、utf8
プラグマは、現在のブロックやファイルの操作が、 Unicode であると明示するのを宣言するために使われました。 このモデルは間違いが見つけられるか、少なくとも、不格好です: 操作に添付するかわりに、"Unicodeness" は、今や、データに持ち込まれています。 唯一残されている、明示的に use utf8
をする必要がある場所は: Perl スクリプト自身が UTF-8 でエンコードされていれば、 識別子の名前、文字の中と、正規表現のリテラルに、UTF-8 を使うことができます。 これは、デフォルトではありません。 なぜなら、レガシーの 8-bit データのスクリプトが壊れるからです。 utf8 を参照してください。
Perl は、Perl 5.6 より前での 8 ビットネイティブのバイト列の文字列と、 Unicode 文字の文字列の両方をサポートします。 方針は、Perl は、可能な限り長く 8 ビットバイト列としてデータを 保とうとします。 ですが、Unicode 性が避けられなくなった時点で、 データは透過的に Unicode に昇格されます。
内部的には、Perl は、プラットフォームの 8 ビット文字セット (例えば、Latin-1)は、デフォルトは UTF-8 ですが、Unicode 文字列に エンコードします。 特に、文字列中の、全てのコードポイントは、0xFF
以下であれば、 Perl は、ネイティブの 8 ビットの文字セットを使います。 そうでなければ、UTF-8 を使います。
Perlのユーザは普通は、Perl がその内部文字列をたまたま、どのように エンコードするかを、知る必要も、気にする必要もありませんが、Unicode 文字列を PerlIO 層なしに -- 「デフォルトの」エンコーディングで -- ストリームに 出力しようとすると、関係するようになります。 このようなケースでは、内部的に使われている生のバイト列(それぞれの 文字列の必要に応じて、ネイティブの文字セットか、UTF-8)が使われます。 それらの文字列に、0x00FF を超える文字があれば、"Wide character" の警告が 出されます。
たとえば、
perl -e 'print "\x{DF}\n", "\x{0100}\x{DF}\n"'
ネイティブのバイト列と UTF-8 の、まったく役に立たない混合もまた、 同様に警告を出します:
Wide character in print at ...
UTF-8 を出力するために、:encoding
か :utf8
出力層を使います。 先頭にこれを追加することで:
binmode(STDOUT, ":utf8");
このサンプルプログラムが、出力が完全に UTF-8 であることを保証し、 プログラムの警告を削除します。
-C
コマンドラインスイッチか、PERL_UNICODE
環境変数のどちらか一方を 使うことで、標準ファイルハンドルと、デフォルトの open()
層と、 @ARGV
の UTF-8 化を自動的に有効に出来ます; perlrun の -C
スイッチのドキュメントを見て下さい。
このことは、Perl が他のソフトウェアの動きを予測することを意味するのに 気をつけて下さい: Perl が STDIN が UTF-8 であるべきと信じるように主導されていて、 他のコマンドからくる STDIN が UTF-8 でなければ、 Perl は、不正な UTF-8 であると文句を言います。
Unicode と、I/O の結合の特徴もまた、新しい PerlIO の特徴を使うことを 必要とします。 ほとんど全ての Perl5.8 プラットフォームは、PerlIO を使います。 ですが: "perl -V" を動かして、useperlio=define
を見れば、PerlIO を 使っているかどうか、わかります。
Perl 5.8.0 は、EBCDIC プラットフォームでもまた、Unicode をサポートします。 ここでは、各ステップで追加の変換が必要になるので、Unicode サポートは 実装が若干より複雑になります。 いくつかの問題が残っています; 詳しくは perlebcdic を参照してください。
ともかく、EBCDIC プラットフォームでの Unicode 対応は、EBCDIC プラットフォームではうまく動かなかった 5.6 シリーズよりは改善しています。 EBCDIC プラットフォームでは、内部 Unicode エンコーディング形式は UTF-8 ではなく UTF-EBCDIC です。 この違いは、ASCII 文字はそのまま UTF-8 にエンコードされるという点において "ASCII セーフ" ですが、一方 UTF-EBCDIC は "EBCDIC セーフ" です。
0xFF
を超えるコードポイントのリテラルで Unicode 文字を作るためには、 \x{...}
記法をダブルクォートされた文字列の中で使います。
my $smiley = "\x{263a}";
同様に、正規表現の中でも使えます。
$smiley =~ /\x{263a}/;
chr()
を使って、実行時に:
my $hebrew_alef = chr(0x05d0);
全てのこれらの数字のコードを見つける方法は、"Further Resources" を 参照してください。
当然、ord()
は、逆を行います: 文字をコードポイントに変えます。
0x100
(10 進の 256)未満の引数の、\x..
({}
なしで、 2 つの 16 進数の数字のみです)と、\x{...}
と、chr(...)
は、古い Perl との互換性のために、8 ビットの文字列を生成します。 x100
かそれ以上の引数では、常に Unicode 文字が生成されます。 何が何でも、数字の値の Unicode 文字を、強制的に生成したければ、 \x..
、\x{...}
、chr()
の代わりに、pack("U", ...)
を使って下さい。
ダブルクォートされた文字列内で、名前で文字を呼び出すために、 charnames
プラグマを使うこともできます:
use charnames ':full';
my $arabic_alef = "\N{ARABIC LETTER ALEF}";
そして、上述のように、数字を Unicode 文字に、pack()
できます:
my $georgian_an = pack("U", 0x10a0);
\x{...}
と、\N{...}
の両方は、コンパイル時の文字列定数です: その中に変数を使うことはできません。 類似のことを実行時にしたいなら、c<chr()> と、charnames::vianame()
を 使ってください。
結果を Unicode 文字に強制したいなら、特別な、"U0"
接頭辞を使って下さい。 これは引数を消費しませんが、引き続くバイト列を Unicode 文字の UTF-8 エンコーディングとして解釈させます:
my $chars = pack("U0W*", 0x80, 0x42);
同様に、特殊な "C0"
接頭辞を使うことによって、このような UTF-8 の解釈を 停止させることができます。
Unicode を扱うことは、多くの部分にとって、透過的です: 文字列をいつものように使うだけです。 index()
、length()
、substr()
のような関数は Unicode 文字列で 動きます; 正規表現も Unicode 文字列で動きます(perlunicode と perlretut を 参照してください)。
Perl は combining character sequences を別々の文字と考えていることに 注意して下さい。 ですので、例えば
use charnames ':full';
print length("\N{LATIN CAPITAL LETTER A}\N{COMBINING ACUTE ACCENT}"), "\n";
これは 1 ではなく、2 を表示します。 唯一の例外は、正規表現に、combining character sequence に マッチするために、\X
がある場合です。
しかし、レガシーエンコーディング、I/O、そしてある種の特殊な状況では、 人生はそれほど透過的ではありません:
レガシーデータと Unicode とを組み合わせる時は、 レガシーデータを Unicode に昇格しなければなりません。 通常、ISO 8859-1 (か、必要なら EBCDIC)が仮定されます。
Encode
モジュールは多くのエンコーディングを知っており、 それらのエンコーディングの間の変換をするインターフェースを持っています。
use Encode 'decode';
$data = decode("iso-8859-3", $data); # convert from legacy to utf-8
通常、Unicode データを書き出すことは、
print FH $some_string_with_unicode, "\n";
Unicode 文字列を内部的にエンコードするのにたまたまつかわれている、 生のバイト列を生成することです。 Perl の内部エンコーディングは、そのときに、文字列にたまたまある文字と 同じように、システム依存です。 どの文字も、コードポイントが 0x100
以上なら、警告がでます。 出力が明示的に、望んでいるエンコーディングにレンダリングされていることを 保証し、警告を避けるために、望んでいるエンコーディングでストリームを open してください。 いくつか例示します:
open FH, ">:utf8", "file";
open FH, ">:encoding(ucs2)", "file";
open FH, ">:encoding(UTF-8)", "file";
open FH, ">:encoding(shift_jis)", "file";
すでに開かれているストリームに関しては、binmode()
を使います:
binmode(STDOUT, ":utf8");
binmode(STDOUT, ":encoding(ucs2)");
binmode(STDOUT, ":encoding(UTF-8)");
binmode(STDOUT, ":encoding(shift_jis)");
エンコーディング名のマッチングはルーズです: 大文字小文字は重要ではなく、 多くのエンコーディングでは、いくつかの別名があります。 :utf8
層は、常に、きっちりとそのように指定される必要があります。 このことは、エンコーディング名のルーズなマッチングの対象では ありません。 データが妥当な UTF8 であるかどうかを検証せずに受け入れるので、入力に 対しては :utf8
は安全ではないことにも注意してください。
:utf8
層に関しては、PerlIO を参照してください; :encoding()
に関しては、Encode::PerlIO を参照してください; Encode
モジュールでサポートされている、多くのエンコーディングに関しては、 Encode::Supported を参照してください。
Unicode かレガシーのエンコーディングどちらかでたまたまエンコードされている ファイルを読み込んでも、Perl の目で、魔法のように、データが Unicode に 変わったりしません。 そうするためには、ファイルを開くときに、適切な層を指定します。
open(my $fh,'<:encoding(utf8)', 'anything');
my $line_of_unicode = <$fh>;
open(my $fh,'<:encoding(Big5)', 'anything');
my $line_of_unicode = <$fh>;
I/O 層は、もっと柔軟に、open
プラグマでもまた、指定することが出来ます。 open を参照するか、次の例を見て下さい。
use open ':encoding(utf8)'; # input/output default encoding will be UTF-8
open X, ">file";
print X chr(0x100), "\n";
close X;
open Y, "<file";
printf "%#x\n", ord(<Y>); # this should print 0x100
close Y;
open
プラグマで、:local
層も使えます:
BEGIN { $ENV{LC_ALL} = $ENV{LANG} = 'ru_RU.KOI8-R' }
# the :locale will probe the locale environment variables like LC_ALL
use open OUT => ':locale'; # russki parusski
open(O, ">koi8");
print O chr(0x430); # Unicode CYRILLIC SMALL LETTER A = KOI8-R 0xc1
close O;
open(I, "<koi8");
printf "%#x\n", ord(<I>), "\n"; # this should print 0xc1
close I;
ストリームからファイルが読まれるときに、特定のエンコーディングから、 データを変換する I/O ストリーム上の透過的な層です。 その結果は常に Unicode です。
open プラグマは、デフォルトの層を設定することで、プラグマの後の 全ての open()
呼び出しに影響します。 あるストリームだけに影響を限定したいなら、open()
呼び出しで明示的な 層を使って下さい。
binmode()
を使って、すでに開かれているストリームのエンコーディングを 変えることが出来ます; "binmode" in perlfunc を参照してください。
:locale
は、現在(Perl 5.8.0 の時点で)、open()
と binmode()
では 動きません。 open
プラグマでのみ動きます。 :utf8
と :encoding(...)
メソッドは、全ての open()
、binmode()
、 open
プラグマで動きます。
似たようなものに、ストリームに書き出すときに、自動的に Unicode を 特定のエンコーディングに変換する、出力ストリームの I/O 層を使うかも 知れません。 例えば、次のようなコードの断片は、(ISO-2022-JP, またの名を JIS として エンコードされている)" text.jis" ファイルの内容を、UTF-8 として エンコードされる "text.utf8" ファイルにコピーします。
open(my $nihongo, '<:encoding(iso-2022-jp)', 'text.jis');
open(my $unicode, '>:utf8', 'text.utf8');
while (<$nihongo>) { print $unicode $_ }
open()
と、open
プラグマの両方で使われているエンコーディングの 名前は、フレキシブルな名前でも使えます: koi8-r
と、KOI8R
は、 両方とも理解されます。
ISO、MIME、IANA、様々な他の標準化機関が認識している、一般的な エンコーディングが認識されます; より詳細なリストは、 Encode::Supported を参照してください。
read()
は、文字を読み、文字の数を返します。 seek()
と tell()
は、バイトカウントに関して操作します。 sysread
と sysseek()
も同様です。
デフォルト層がなければ、入力になんの変換もしないのがデフォルトの 振る舞いなので、繰り返しデータをエンコーディングすることで、 ファイルを展開し続けるコードを誤って書きやすいです。
# BAD CODE WARNING
open F, "file";
local $/; ## read in the whole file of 8-bit characters
$t = <F>;
close F;
open F, ">:encoding(utf8)", "file";
print F $t; ## convert to UTF-8 on output
close F;
このコードを 2 回実行すると、file の内容は、UTF-8 に、2 回 エンコードされます。 use open 'encoding(utf8)'
は、バグを避けるでしょう; もしくは、UTF-8 として入力するために、File を、明示的に開くことです。
注意: :utf8
と :encoding
の機能は、Perl が新しい PerlIO の機能で ビルドされている場合(ほとんどのシステムで、それがデフォルトです)にのみ 動作します。
Unicode を含んでいる Perl のスカラを、単純な ASCII(か、EBCDIC)の テキストとして、表示したいかもしれません。 下のサブルーチンは、引数を変換して、255 より大きいコードポイントの Unicode 文字を、\x{...}
として表示し、(\n
のような)制御文字は、 \x..
として表示します。 残りの文字は、そのまま表示します:
sub nice_string {
join("",
map { $_ > 255 ? # if wide character...
sprintf("\\x{%04X}", $_) : # \x{...}
chr($_) =~ /[[:cntrl:]]/ ? # else if control character ...
sprintf("\\x%02X", $_) : # \x..
quotemeta(chr($_)) # else quoted or as themselves
} unpack("W*", $_[0])); # unpack Unicode characters
}
たとえば、
nice_string("foo\x{100}bar\n")
は、次のような文字列になり:
'foo\x{0100}bar\x0A'
表示可能になります。
演算子 ~ と、vec() についてのちょっとした補足
演算子 ~
は、255 を超える序数の値の文字を含んでいる文字列で、 使われると、驚くべき結果になるでしょう。 そのようなケースでは、その結果は文字の内部的なエンコーディングで一貫性が あります。 しかし、他の多くでは違います。 ですので、そのようなことはしないでください。 vec()
も同様です: コードポイントの値ではなく、内部的にエンコードされた、 Unicode 文字列のビットパターンを操作することになります; おそらく、それは望んだことではないでしょう。
Perl の内部エンコーディングをのぞき見る
Perl がどのように、特定の Unicode 文字列をエンコードしているかを、 Perl の普通のユーザは気にするべきではありません (Unicode で文字列の内容に達する普通の方法 -- 入出力によって -- は、常に 明示的に定義された I/O 層を経由すべきだからです)。 ですが、もし必要なら、隠れている裏側を見る 2 つの方法があります。
Unicode 文字の内部エンコーディングの内側を覗き見る方法の 1 つは、 エンコーディングが何であろうとも文字列のバイト列を得るために unpack("C*", ...
を使うか、UTF-8 エンコーディングのバイト列を得るために unpack("U0..", ...)
を使うことです:
# this prints c4 80 for the UTF-8 bytes 0xc4 0x80
print join(" ", unpack("U0(H2)*", pack("U", 0x100))), "\n";
もう一つの方法は、Dvel::Peek モジュールを使うことです:
perl -MDevel::Peek -e 'Dump(chr(0x100))'
これは、FLAGS の UTF8
フラグと、UTF-8 バイトと、PV
の中の Unicode 文字の両方を見せます。 このドキュメントの後にある、utf8::is_utf8()
機能についての議論も 参照してください。
文字列の等価性
文字列の等価性の疑問は、Unicode でいくぶん複雑になります。 "等価" で、何を意味していますか?
(IS LATIN CAPITAL LETTER A WITH ACCUTE
と LATIN CAPITAL LETTER A
は、等しいでしょうか?)
短く答えれば次のようになります。 デフォルトでは、Perl は(eq
と、ne
で)等価性を 比較しますが、これらは、文字のコードポイントでのみに基づいています。 上のケースでは、答えはいいえです(0x00C1 != 0x0041 ですから)。 しかし、どんな CAPITAL LETTER A も等しいと考えるべき時や、大文字小文字に 関わらずどんな A も等しいと考えるべき時もあります。
長く答えるなら、文字の正規化と大文字小文字の問題を考える必要があります: Unicode::Normalize、Unicode テクニカルレポート #15 と #21 である Unicodde Normalization Forms と Case Mappings ( http://www.unicode.org/unicode/reports/tr15/, http://www.unicode.org/unicode/reports/tr21/ ) を参照してください。
Perl 5.8.0 から、Case Mappings/SpecialCasing の、 "Full" ケースフォールディングが実装されています。
文字列の照合(Collation)
文字列がうまくソートされている(あるいは Unicode の業界用語を使えば、 照合されている(collated))のを好みます。 ですが、再び、照合で何を意味していますか?
(LATIN CAPITAL LETTER A WITH ACUTE
は、 LATIN CAPITAL LETTER A WITH GRAVE
より、 前でしょうか後でしょうか?)
短く答えれば次のようになります。 Perl は、文字列を、(lt
、le
、cmp
、ge
、gt
)で比較しますが、 これらは、文字のコードポイントでのみに基づいています。 上のケースでは、答えは、0x00C1
> 0x00C0
ですので、"後"になります。
長く答えるなら、"依存して"います。 良い答えは、(とても少なくとも)言語のコンテキストを知らずには、 与えられません。 Unicode::Collate, Unicode Collation Algorithm http://www.unicode.org/unicode/reports/tr10/ を参照してください。
文字の範囲とクラス
正規表現の文字クラス(/[a-z]/
)内と、tr///
(y///
としても知られる) 演算子内では、自動的には Unicode 対応にはなりません。 これが意味することは、[A-Za-z]
は、自動的に "全てのアルファベット文字"を 意味するようにはなりません; 8 ビットの文字で意味します; このケースでは、/[[:alpha:]]/
を使うべきです。
正規表現内のこのような特定の文字クラスに、様々な Unicode プロパティ -- \pL
、または、この特別なケースでは、たぶん、\p{Alphabetic}
を 使うことができます。 文字の範囲の終わりのポイントとして、Unicode のコードポイントを 使うことが出来ます。 ですが、ある範囲を特定するのに結びつける何の魔法もありません。 詳しいことは--数ダースの Unicode 文字クラスがあります-- perlunicode を見て下さい。
文字列から数字への変換
Unicode は、なじみのある、アラビアやインドの数字のような 0 から 9 に加えて、 複数の他の 10 進数--と数字の--文字を、定義します。 Perl は、ASCII の 0 から 9(と、16 進法の ASCII の a から f)以外の数字の、 文字列から数への変換をサポートしません。
古いスクリプトは壊れるでしょうか?
たぶん、壊れません。 どうにかして、Unicode 文字を生成していなければ、古い挙動は保護されます。 振る舞いが変更され、Unicode を生成し始める唯一のものは、古い chr()
は 引数として 255 を超える値が指定されると、255 を法とした文字が生成される というものです。 例えば、chr(300)
は、chr(45)
あるいは (ASCII の)"-" と同じでした。 現在ではそれは、LATIN CAPITAL LETTER I WITH BREVE です。
私のスクリプトを Unicode で動かすには?
Unicode データを生成するまで、ほとんど何もする必要はありません。 もっとも重要なものは、Unicode として、入力を得ることです; なので、以前の I/O の議論を見て下さい。
Unicode の文字列かどうかを知るには?
気にすることはありません。 ええ、本当に、気にするべきではありません。 ええ、本当に。 気にする必要があるなら -- このケースは上で書いています -- 本当に正しく、Unicode の透過性を得ていないことを意味します。
オーケー、どうしてもというなら:
print utf8::is_utf8($string) ? 1 : 0, "\n";
しかし、これは、文字列の文字のすべてが UTF-8 でエンコードされているとか、 文字のすべてが 0xFF(255)(あるいは 0x80(128)) より大きいコードポイントを 持つとか、文字列に文字が含まれているかとかいうことを 意味するわけではないことに注意してください。 is_utf8()
がすることの全ては、$string
につけられている内部の "utf8ness" フラグの値を返すことです。 フラグが無効であれば、スカラ内のバイト列は、シングルバイト エンコーディングとして解釈されます。 フラグが有効であれば、スカラ内のバイト列は、(マルチバイト、可変長の) UTF-8 でエンコードされた文字のコードポイントとして解釈されます。 (ダブルクオートされた語句、明示的な連結、printf/sprintf パラメタ 置換によって)非 UTF-8 と、UTF-8 のスカラがマージされた場合、この結果は、 バイト文字列のコピーが UTF-8 で昇格されたかのように、 UTF-8 でエンコードされています: 例えば、
$a = "ab\x80c";
$b = "\x{100}";
print "$a = $b\n";
出力する文字列は UTF-8 エンコードされた ab\x80c = \x{100}\n
になりますが、 $a
は、バイトエンコードされたままです。
文字列の長さではなく、文字列のバイト長を知る必要があるかもしれません。 そのためには、Encode::encode_utf8()
関数か、bytes
プラグマの どちらかを使い、定義された length()
関数を使うだけです:
my $unicode = chr(0x100);
print length($unicode), "\n"; # will print 1
require Encode;
print length(Encode::encode_utf8($unicode)), "\n"; # will print 2
use bytes;
print length($unicode), "\n"; # will also print 2
# (the 0xC4 0x80 of the UTF-8)
あるエンコーディングで、データが妥当でないことを検出するには?
Encode
パッケージを使って、それを変換してみてください。 例えば、
use Encode 'decode_utf8';
eval { decode_utf8($string, Encode::FB_CROAK) };
if ($@) {
# $string is valid utf8
} else {
# $string is not valid utf8
}
または unpack
を使ってデコードしてみてください:
use warnings;
@chars = unpack("C0U*", $string_of_bytes_that_I_think_is_utf8);
妥当でなければ、Malformed UTF-8 character
の警告が出ます。 "C0" は、「文字列を文字単位で処理する」ことを意味します。 それ以外では、unpack("U*", ...)
は (フォーマット文字列が U
で 始まっている場合のデフォルトである)U0
モードで動作し、ターゲット文字列の UTF08 エンコーディングでのバイト数を返し、このようなことは常に動作します。
バイナリデータを特定のエンコーディングに変換するには? また、その逆は?
たぶん、思うようには有益ではないでしょう。 ふつう、必要とするべきではありません。
ある意味では、あなたが尋ねようとしていることはほとんど意味はありません: エンコーディングは文字のためのもので、バイナリデータは「文字」ではないので、 「データ」を何かのエンコーディングに変換するということは、 バイナリデータの文字セットとエンコーディングが分かっていない限り無意味です; そして分かっているならそれは単なるバイナリデータではないですよね?
どのエンコーディングで解釈するべきか分かっている生のバイト列がある場合、 Encode
が使えます:
use Encode 'from_to';
from_to($data, "iso-8859-1", "utf-8"); # from latin-1 to utf-8
from_to()
の呼び出しは $data
のバイト列を変更しますが、Perl が 関知する限りにおいては文字列の性質は何も変わりません。 呼び出しの前後の両方において、文字列 $data
は単に 8 ビットのバイトの 塊です。 Perl が関知するかぎりにおいては、文字列のエンコーディングは 「システムにネイティブな 8 ビットのバイト列」のままです。
これを架空の 'Translate' モジュールと関連付けることもできます:
use Translate;
my $phrase = "Yes";
Translate::from_to($phrase, 'english', 'deutsch');
## phrase now contains "Ja"
文字列の内容は変わりますが、文字列の性質は変わりません。 Perl は文字列の内容が肯定を意味するという呼び出し前の状態よりも多く、 呼び出しによって何かを知ることはありません。
データの変換に戻ります。 もしシステムのネイティブな 8 ビットエンコーディング(例えば、Latin-1, EBCDIC など)のデータを持っている(あるいは欲しい)場合は、Unicode との変換に pack/unpack を使えます。
$native_string = pack("W*", unpack("U*", $Unicode_string));
$Unicode_string = pack("U*", unpack("W*", $native_string));
あなたはバイト列が妥当な UTF-8 であると 分かっている けれども、Perl が 知らない場合、Perl に信じさせることもできます:
use Encode 'decode_utf8';
$Unicode = decode_utf8($bytes);
または:
$Unicode = pack("U0a*", $bytes);
整形された UTF-8 はバイト列に変換できますが、単にランダムなバイナリデータを UTF-8 に変換したいのなら、それはできません。 全てのランダムなバイト列が整形された UTF-8 にはなりません。. 前者のためには unpack("C*", $string)
が使えますし、 pack("U*", 0xff, ...)
を使って整形された Unicode データを作成できます。
Unicode を表示するには? Unicode を入力するには?
http://www.alanwood.net/unicode/ と http://www.cl.cam.ac.uk/~mgk25/unicode.html を参照してください。
伝統的なロケールと Unicode は、どのように動きますか?
Perl では、あまりうまくありません。 locale
プラグマでロケールを使うことを避けて下さい。 どちらか片方だけを使ってください。 しかし、-C
スイッチと、それに対応する環境変数である $ENV{PERL_UNICODE}
の説明のために、perlrun を参照してください; 様々な Unicode の機能が、どのように可能になっているのか、たとえば、 ロケールの設定によって、が、わかります。
Unicode 標準は、16 進記法を使うのを好みます。 それは、256 の文字のブロックに Unicode を分割しているのが、 他の表記よりわかりやすいからです。 10 進記法を使うことも出来ますが、16 進記法を使うことを学べば、 Unicode 標準との暮らしが楽になります。 例えば、U+HHHH
表記は、16 進記法を使います。
0x
の接頭辞は、16 進の数字を意味しています。 数字は、0-9 および a-f(か、A-F、大文字小文字は問いません)です。 それぞれの 16 進の数字は 4 ビット、1/2 バイトを表します。 print 0x..., "\n"
は 16 進数を 10 進で見せます。 printf "%x\n", $decimal
は 10 進数を 16 進で見せます。 "hex digits" の 16 進の数字があるなら、hex()
関数を使うことが出来ます。
print 0x0009, "\n"; # 9
print 0x000a, "\n"; # 10
print 0x000f, "\n"; # 15
print 0x0010, "\n"; # 16
print 0x0011, "\n"; # 17
print 0x0100, "\n"; # 256
print 0x0041, "\n"; # 65
printf "%x\n", 65; # 41
printf "%#x\n", 65; # 0x41
print hex("41"), "\n"; # 65
Unicode Consortium
http://www.unicode.org/
Unicode FAQ
http://www.unicode.org/unicode/faq/
Unicode Glossary
http://www.unicode.org/glossary/
Unicode Useful Resources
http://www.unicode.org/unicode/onlinedat/resources.html
Unicode and Multilingual Support in HTML, Fonts, Web Browsers and Other Applications
http://www.alanwood.net/unicode/
UTF-8 and Unicode FAQ for Unix/Linux
http://www.cl.cam.ac.uk/~mgk25/unicode.html
Legacy Character Sets
http://www.czyborra.com/ http://www.eki.ee/letter/
Unicode サポートのファイルは、Perl をインストールしたディレクトリ内に あります;
$Config{installprivlib}/unicore
Perl 5.8.0 以上ではここです;
$Config{installprivlib}/unicode
Perl 5.6 シリーズではここです。 (大文字小文字を区別しないファイルシステムでは、lib/Unicode との名前の衝突を 避けるために、lib/unicore にリネームされています。) メインの Unicode データファイルは、UnicodeData.txt(か、Perl 5.6.1 の Unicode.301)です。 次のようにして、$Config{installprivlib}
を見つけることができます。
perl "-V:installprivlib"
Unicode::UCD
モジュールを使って、Unicode データファイルから 様々な情報を調べることができます。
Perl 5.8.0 以降にアップグレード出来なくても、まだ、CPAN から利用できる、 Unicode::String
、Unicode::Mmap8
、bUnicode::Map
を使って、 いくつかの Unicode 処理ができます。 GNU recode がインストールされているなら、それの Perl フロントエンドである Convert::Recode
を文字変換のために使えます。
下記のものは、ISO 8859-1 (Latin-1) バイト列から UTF-8 バイト列に (あるいはその逆に)素早く変換するものです。 このコードは古い Perl 5 でも動きます。
# ISO 8859-1 to UTF-8
s/([\x80-\xFF])/chr(0xC0|ord($1)>>6).chr(0x80|ord($1)&0x3F)/eg;
# UTF-8 to ISO 8859-1
s/([\xC2\xC3])([\x80-\xBF])/chr(ord($1)<<6&0xC0|ord($2)&0x3F)/eg;
perlunitut, perlunicode, Encode, open, utf8, bytes, perlretut, perlrun, Unicode::Collate, Unicode::Normalize, Unicode::UCD
Thanks to the kind readers of the perl5-porters@perl.org, perl-unicode@perl.org, linux-utf8@nl.linux.org, and unicore@unicode.org mailing lists for their valuable feedback.
Copyright 2001-2002 Jarkko Hietaniemi <jhi@iki.fi>
This document may be distributed under the same terms as Perl itself.