[Perl] encoding プラグマについて [Perl]
Perl で文字列処理をしているときに行き詰っていろいろ調べていたのですが、Perl-5.8 覚え書き というページに書いてあることが気になりました。
encoding プラグマはグローバルな効果を持ちますから,以下の点に注意が必要です.
- 特定のスコープだけ encoding プラグマを無効化することはできません.
関数 foo の内部だけは,単なるバイト列として扱って欲しいと考えて, 以下のような指定をしても動きません.
sub foo { no encoding; $str = "日本語EUCのバイト列‥‥とは解釈されない"; }
- 他の文字コードで記述されたモジュールを利用できません.
ISO-2022-JP や Shift-JIS など他の文字コードで記述されているモジュールも 日本語 EUC で記述されていると一括して見なされてしまいます. したがって,それらのモジュール中で使われている文字は,正常に解釈されないでしょう. ただし,UTF-8 で記述されていて,かつ, utf8 プラグマが指定されているモジュールは利用できます.
use utf8; # ... UTF-8 で記述されたモジュール 1;
- encoding プラグマを複数回指定することはできません.
複数の encoding プラグマが指定された場合は,最後のプラグマだけが意味を持ちます.
スコープが無いのはともかく 「他の言語で記述されたモジュールを利用でき」 ないっていうのは流石にないだろう、と。 perldoc の encoding プラグマの頁 を見てみました。
まず encoding プラグマがスコープを持たない、というのは正しいです。 しかし、encoding プラグマを複数回指定できない、ということはありません。
encoding プラグマには 2 つの役割があり、1 つ目は source code 中に存在する文字列の符号化方式 (encoding) を指定する、というもの。 2 つ目は出入力の Perl IO レイヤを指定するというもの。 1 つ目の役割は、Perl のコンパイル時に効果を発揮します。 そのため、source code の上から順に効果が現れます。 use encoding "xxx";
(もしくは no encoding;
) が出現すると次に use encoding "yyy";
(または no encoding;
) が現れるまで、指定した source code 中の文字列を指定した文字コードで符号化された文字列だと解釈し、自動的に text strings (Unicode 文字列) にします。
2 つ目、入出力時の Perl IO レイヤを指定する、というものですが、入出力を行うのは Perl の実行時の話です。 そのため、文字列の時のように、souce code の上から順に、という風にはならず、最後の use encoding "xxx";
(もしくは no encoding;
) だけが意味を持ちます。 ただし、実行時に処理される binmode で Perl IO レイヤを指定すると、当然ながら binmode が優先されます。
そんなわけで入出力に関しては、確かに Perl-5.8 覚え書き に書いてある通りですが、source code 内の文字列の解釈という点では、use encoding "xxx";
もしくは no encoding;
を何度も書く意味はありますし、スコープはありませんが、特定の部分だけ text strings にしない、ということもできるわけです。
#/usr/local/bin/perl -w
# utf8 で書かれた script
use encoding "utf8";
# 中略
# ここにある文字列は、text strings (Unicode 文字列) となる
sub foo {
no encoding;
$str = "utf8 の binary strings と解釈される";
# ここにある文字列は、binary strings となる
use encoding "utf8"; # スコープが無いので、再度 use しなければならない
}
# ここにある文字列は text strings
よって、モジュール内で use encodeing "xxx";
が使われていると、ちゃんとそのモジュール内でその効果はあります。 ただし、スコープが無いのでモジュールを呼ぶ順番には気をつけなければいけません。 たとえば、main パッケージ内で encoding プラグマを使ったとしましょう。 その直後に、encoding プラグマを使っているモジュールを呼び出してしまった場合、main パッケージのそれ以降は、main パッケージの encoding プラグマではなくモジュールの方の encoding プラグマの効果を受けます。
というわけで、まとめると以下のようになります。
- 特定のスコープだけ encoding プラグマを無効化することはできない
ですが、特定の部分の encoding プラグマを無効化することは出来ます。
- 他の文字コードで記述されたモジュールを利用できない、ということはありません
ただし、スコープが無いので、モジュール内の encoding プラグマが main パッケージ内に影響を及ぼしますし、その逆もありえます。 そのため、モジュールを呼んだ後に、main パッケージ内で encoding プラグマを使用しなければなりません。
- encoding プラグマを複数回指定することはできない、ということはありません
encoding プラグマは、文字コードの指定という役割については次の encoding プラグマまで効果を発揮します。 入出力の文字コードの指定については、最後のプラグマだけが意味を持ちます。
コメント 0