Bu daha çok nasıl YAPILMAMASI gerektiğine dair bir öneridir . Oldukça büyük bir Perl uygulamasında bir hata bulmakta kötü bir zaman geçirdim. Modüllerin çoğunun kendi yapılandırma dosyaları vardı. Yapılandırma dosyalarını bir bütün olarak okumak için, Perl'in bu tek satırını internette bir yerde buldum:
# Bad! Don't do that!
my $content = do{local(@ARGV,$/)=$filename;<>};
Satır ayırıcıyı daha önce açıklandığı gibi yeniden atar. Ama aynı zamanda STDIN'i de yeniden atar.
Bu, bulmam saatler süren en az bir yan etkiye sahipti: Örtülü dosya tanıtıcısını düzgün şekilde kapatmıyor (çünkü close
).
Örneğin, bunu yapmak:
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";
sonuçlanır:
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
Garip olan, satır sayacının $.
her dosya için birer birer artırılmasıdır. Sıfırlanmaz ve satır sayısını içermez. Ve başka bir dosyayı açarken en az bir satır okunana kadar sıfırlanmaz. Benim durumumda şöyle bir şey yapıyordum:
while($. < $skipLines) {<FILE>};
Bu problem nedeniyle, hat sayacı doğru şekilde sıfırlanmadığı için koşul yanlıştı. Bunun bir hata mı yoksa sadece yanlış kod mu olduğunu bilmiyorum ... Ayrıca oder'i close;
aramak close STDIN;
da yardımcı olmuyor.
Bu okunamayan kodu open, string concatenation ve close kullanarak değiştirdim. Bununla birlikte, Brad Gilbert tarafından yayınlanan çözüm, bunun yerine açık bir dosya tanıtıcısı kullandığı için de işe yarıyor.
Baştaki üç satır şu şekilde değiştirilebilir:
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};
dosya tutamacını düzgün kapatır.