ファイルハンドルの概念がわかりにくいので、ちょっと説明。
ファイルハンドルの概念を理解する - Perlゼミ - Perl元気塾のPerl講座
ファイルハンドルと出力 - 2部 Perl言語仕様 - [SMART]
上記の記事にもあるように、ファイルハンドルは具体的な実体があるわけではなく、ファイルハンドルの条件に当てはまる部分をPerlコンパイラがファイルハンドルとして認識してる模様。
シンボルの回でも、ちょっと扱ったけど、ファイルハンドルはシンボルに限らない。
でもまずはシンボルから。
file_handle.plを開いて、
#!/usr/bin/perl
use strict;
my $ret = open(OUT, ">", "test.txt");
if ($ret){
print OUT "ABCDE\n";
close(OUT);
}
シンボルOUTをファイルハンドルとして認識してる。
$ vi file_handle.pl
$ perl file_handle.pl
$ ls
file_handle.pl test.txt
$ cat test.txt
ABCDE
$
シンボルはレキシカル変数ではないので、myを付けて宣言しなくても、コンパイルできるし、strictにも引っ掛からない。
続いて、Perl 5.6未満で、使われていたという、シンボルの型グロブ。
#!/usr/bin/perl
use strict;
my $ret = open(OUT, ">", "test.txt");
if ($ret){
print OUT "ABCDE\n";
*new_name = *OUT;
print *new_name "FGHIJ\n";
close(*new_name);
}
*OUTから*new_nameという別の型グロブに引き渡しても、書き込みできるか。
$ vi file_handle.pl
$ rm test.txt
$ ls
file_handle.pl
$ perl file_handle.pl
String found where operator expected at file_handle.pl line 11, near "*new_name "FGHIJ\n""
(Missing operator before "FGHIJ\n"?)
syntax error at file_handle.pl line 11, near "*new_name "FGHIJ\n""
Execution of file_handle.pl aborted due to compilation errors.
$
ダメだった。
printでコンパイルエラー。
もしかしてprintは型グロブ形式がダメなのかな。
#!/usr/bin/perl
use strict;
my $ret = open(OUT, ">", "test.txt");
if ($ret){
print OUT "ABCDE\n";
*new_name = *OUT;
print new_name "FGHIJ\n";
close(*new_name);
}
*を外してみた。
$ vi file_handle.pl
$ ls
file_handle.pl
$ perl file_handle.pl
$ ls
file_handle.pl test.txt
$ cat test.txt
ABCDE
FGHIJ
$
やっぱり・・・。
#!/usr/bin/perl
use strict;
my $ret = open(*OUT, ">", "test.txt");
if ($ret){
print *OUT "ABCDE\n";
close(*OUT);
}
openに*OUTという感じでファイルハンドルの型グロブを直接指定。
$ vi file_handle.pl
$ rm test.txt
$ ls
file_handle.pl
$ perl file_handle.pl
String found where operator expected at file_handle.pl line 9, near "*OUT "ABCDE\n""
(Missing operator before "ABCDE\n"?)
syntax error at file_handle.pl line 9, near "*OUT "ABCDE\n""
Execution of file_handle.pl aborted due to compilation errors.
$
エラーは出てるけど、これprintだけでは。
#!/usr/bin/perl
use strict;
my $ret = open(*OUT, ">", "test.txt");
if ($ret){
print "open success!\n";
close(*OUT);
}
printに渡すのは止めて、openとcloseだけ確認。
$ vi file_handle.pl
$ perl file_handle.pl
open success!
$
これもか・・・。
つまり、printだけファイルハンドルの型グロブがダメと。
Perl 5.6未満は、ファイルハンドルを変数に入れるのに型ブログに変換していたらしいので、それをやってみる。
#!/usr/bin/perl
use strict;
my $tgfh = *OUT;
my $ret = open($tgfh, ">", "test.txt");
if ($ret){
print $tgfh "ABCDE\n";
close($tgfh);
}
こうすると、
$ vi file_handle.pl
$ rm test.txt
$ perl file_handle.pl
$ cat test.txt
ABCDE
$
今度は、printでも問題なく通った。
型グロブにして変数に入れればいいのか。
さて、型ブログのリファレンスという方法もある。
#!/usr/bin/perl
use strict;
my $rtgfh = \*OUT;
my $ret = open($rtgfh, ">", "test.txt");
if ($ret){
print $rtgfh "ABCDE\n";
close($rtgfh);
}
これも、
$ vi file_handle.pl
$ rm test.txt
$ perl file_handle.pl
$ cat test.txt
ABCDE
$
通る。
で、今は5.6以上なので、普通のスカラ変数でも通るのでは。
#!/usr/bin/perl
use strict;
my $symbol = OUT;
my $ret = open($symbol, ">", "test.txt");
if ($ret){
print $symbol "ABCDE\n";
close($symbol);
}
こうすると、
$ vi file_handle.pl
$ rm test.txt
$ perl file_handle.pl
Bareword "OUT" not allowed while "strict subs" in use at file_handle.pl line 6.
Execution of file_handle.pl aborted due to compilation errors.
$
ダメか。
でも、strictって出てるから、外せばいけるのでは。
"use strict;"コメントしたら、
$ vi file_handle.pl
$ perl file_handle.pl
$ cat test.txt
ABCDE
$
通った。
というわけで、シンボル、型グロブ、型グロブのリファレンス、という3パターンが、(一部の例外を除いて)ファイルハンドルとして認識されるのがわかった。
あと2つあったり、5.6以降の現代的な書き方があったりするけど、それは次以降で。
Sample/perl/file_handle/file_handle/src/file_handle at master · bg1bgst333/Sample · GitHub