ぱるも日記

ぱるも日記は id:palmo がプログラミング言語 Perl を1から勉強していく日記です。

2006-06-20 特別なファイルハンドル

特殊ファイルハンドル DATA

Perl コンパイラがコードを解釈する段階で、「__END__」もしくは「__DATA__」という行(トークン)を見つけると、それ以降からファイルの終わりまでコードとして解釈されなくなります。コメントのように、何を書いてもコードとしては実行されませんが、これらのテキストは「DATA」という特殊なファイルハンドルで参照する事ができます。

特殊なファイルハンドルといっても、普通のファイルハンドルと同じように行入力演算子(<>)などで読み込む事ができるので、コード中に簡単なデータを埋め込みたい時に便利です。

「__END__」と書いた場合は、どんなパッケージでも常に main パッケージの DATA ファイルハンドル(main::DATA)に関連付けられます。「__DATA__」と書いた場合は、現在のパッケージの DATA ファイルハンドル(__PACKAGE__::DATA)に関連付けられます。

use strict;
 
while(<DATA>) { print; }
 
__END__
Hello, world!
I am Palmo the Perl student.

__END__ 以降のテキストがコードとして評価されるとエラーになりますが、実際にはエラーは発生しません。

実行結果は以下の通りです。

Hello, world!
I am Palmo the Perl student.

ちゃんと動きますね。(^_^)

__END__ を __DATA__ に変えても動きます。


では、複数のパッケージで試してみましょう。

# Data1.pl
package Data1;
 
1;
 
__DATA__
Here is after __DATA__ in Data1
# Data2.pl
package Data2;
 
1;
 
__END__
Here is after __END__ in Data2

Data1.pl と Data2.pl として保存します。似たようなコードですが、__DATA__ と __END__ の違いがあります。

パッケージの最後にある式の値はパッケージの評価結果となります。ここでは「1;」として 1 を返しています。パッケージを require する場合、真を返さないとエラーとなってしまうので、その対策です。

use strict;
require "Data1.pl";
require "Data2.pl";
 
sub show($*) {
  my ($name, $data_ref) = @_;
  print "$name : ";
  while(<$data_ref>) { chomp; print; }
  print "\n";
}
 
show("main", main::DATA);
show("Data1", Data1::DATA);
show("Data2", Data2::DATA);
 
__END__
Here is after __END__ in main

Data1.pl と Data2.pl をそれぞれ読み込んでいます。show 関数は名前とファイルハンドルを受け取って、その内容を表示する関数です。ファイルハンドルは型グロブとして受け取っています。

これを同じフォルダに保存して実行すると……エラーが発生します。

main : Here is after __END__ in main
Data1 : Here is after __DATA__ in Data1
readline() on unopened filehandle at D:\home\palmo\data.pl line 8.
Data2 :

Data2::DATA を読み込もうとして、「開かれていないファイルハンドル」とエラーになってしまいました。つまり、Data2::DATA は存在しないという事です。これは、Data2 で __END__ を使っていて、main::DATA に関連付けられたからですね。

試しに Data2 の中の __END__ を __DATA__ に置き換えると、上手く動きます。

# Data2.pl
package Data2;
 
1;
 
__DATA__
Here is after __DATA__ in Data2
main : Here is after __END__ in main
Data1 : Here is after __DATA__ in Data1
Data2 : Here is after __DATA__ in Data2

メインパッケージ以外では __DATA__ を使う方が無難そうですね。(^_^)

cooscoos 2016/04/13 17:23 "sub show($*) {"

"($*)"
どういう意味ですか?

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/palmo/20060620/data