これは、より多くの方法についての提案である、NOTそれを行います。かなり大きなPerlアプリケーションのバグを見つけるのに苦労しました。ほとんどのモジュールには独自の構成ファイルがありました。設定ファイル全体を読むために、インターネット上のどこかにこのPerlの1行を見つけました。
# Bad! Don't do that!
my $content = do{local(@ARGV,$/)=$filename;<>};
前に説明したように、行区切りを再割り当てします。ただし、STDINも再割り当てされます。
これには少なくとも1つの副作用があり、見つけるのに何時間もかかりました。暗黙のファイルハンドルが適切に閉じられません(まったく呼び出さclose
れないため)。
たとえば、次のようにします。
use strict;
use warnings;
my $filename = 'some-file.txt';
my $content = do{local(@ARGV,$/)=$filename;<>};
my $content2 = do{local(@ARGV,$/)=$filename;<>};
my $content3 = do{local(@ARGV,$/)=$filename;<>};
print "After reading a file 3 times redirecting to STDIN: $.\n";
open (FILE, "<", $filename) or die $!;
print "After opening a file using dedicated file handle: $.\n";
while (<FILE>) {
print "read line: $.\n";
}
print "before close: $.\n";
close FILE;
print "after close: $.\n";
結果は:
After reading a file 3 times redirecting to STDIN: 3
After opening a file using dedicated file handle: 3
read line: 1
read line: 2
(...)
read line: 46
before close: 46
after close: 0
奇妙なことに、$.
ファイルごとに行カウンターが1つずつ増加します。リセットされず、行数も含まれません。そして、少なくとも1行が読み込まれるまで、別のファイルを開いたときにゼロにリセットされません。私の場合、私は次のようなことをしていました:
while($. < $skipLines) {<FILE>};
この問題のため、ラインカウンターが正しくリセットされなかったため、条件はfalseでした。これがバグなのか、単に間違ったコードなのかはわかりません... close;
oderを呼び出しclose STDIN;
ても役に立ちません。
この判読できないコードは、open、string連結、closeを使用して置き換えました。ただし、代わりに明示的なファイルハンドルを使用するため、Brad Gilbertによって投稿されたソリューションも機能します。
最初の3行は次のように置き換えることができます。
my $content = do{local $/; open(my $f1, '<', $filename) or die $!; my $tmp1 = <$f1>; close $f1 or die $!; $tmp1};
my $content2 = do{local $/; open(my $f2, '<', $filename) or die $!; my $tmp2 = <$f2>; close $f2 or die $!; $tmp2};
my $content3 = do{local $/; open(my $f3, '<', $filename) or die $!; my $tmp3 = <$f3>; close $f3 or die $!; $tmp3};
これにより、ファイルハンドルが適切に閉じます。