Ini lebih merupakan saran tentang bagaimana TIDAK melakukannya. Saya baru saja mengalami kesulitan menemukan bug di aplikasi Perl yang agak besar. Sebagian besar modul memiliki file konfigurasinya sendiri. Untuk membaca file konfigurasi secara keseluruhan, saya menemukan satu baris Perl ini di suatu tempat di Internet:
# Bad! Don't do that!
my $content = do{local(@ARGV,$/)=$filename;<>};
Ini menetapkan kembali pemisah garis seperti yang dijelaskan sebelumnya. Tetapi itu juga menetapkan ulang STDIN.
Ini memiliki setidaknya satu efek samping yang menghabiskan waktu berjam-jam untuk menemukannya: Ini tidak menutup pegangan file implisit dengan benar (karena tidak memanggil close
sama sekali).
Misalnya, melakukan itu:
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";
menghasilkan:
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
Hal yang aneh adalah, bahwa penghitung baris $.
meningkat untuk setiap file satu per satu. Ini tidak diatur ulang, dan tidak berisi jumlah baris. Dan itu tidak diatur ulang ke nol saat membuka file lain sampai setidaknya satu baris dibaca. Dalam kasus saya, saya melakukan sesuatu seperti ini:
while($. < $skipLines) {<FILE>};
Karena masalah ini, kondisinya salah karena penghitung saluran tidak diatur ulang dengan benar. Saya tidak tahu apakah ini bug atau kode yang salah ... Panggilan close;
oder close STDIN;
juga tidak membantu.
Saya mengganti kode yang tidak dapat dibaca ini dengan menggunakan open, string concatenation, dan close. Namun, solusi yang diposting oleh Brad Gilbert juga berfungsi karena menggunakan pegangan file eksplisit sebagai gantinya.
Tiga baris di awal dapat diganti dengan:
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};
yang dengan benar menutup pegangan file.