Questo è più un suggerimento su come NON farlo. Ho appena avuto problemi a trovare un bug in un'applicazione Perl piuttosto grande. La maggior parte dei moduli aveva i propri file di configurazione. Per leggere i file di configurazione nel loro insieme, ho trovato questa singola riga di Perl da qualche parte su Internet:
# Bad! Don't do that!
my $content = do{local(@ARGV,$/)=$filename;<>};
Riassegna il separatore di riga come spiegato prima. Ma riassegna anche STDIN.
Questo ha avuto almeno un effetto collaterale che mi è costato ore da trovare: non chiude correttamente l'handle del file implicito (poiché non chiama close
affatto).
Ad esempio, in questo modo:
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";
risultati in:
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
La cosa strana è che il contatore di riga $.
viene aumentato di uno per ogni file. Non è ripristinato e non contiene il numero di righe. E non viene azzerato quando si apre un altro file fino a quando non viene letta almeno una riga. Nel mio caso, stavo facendo qualcosa del genere:
while($. < $skipLines) {<FILE>};
A causa di questo problema, la condizione era falsa perché il contatore di riga non è stato reimpostato correttamente. Non so se sia un bug o semplicemente un codice sbagliato ... Anche chiamare close;
oder close STDIN;
non aiuta.
Ho sostituito questo codice illeggibile usando open, concatenazione di stringhe e close. Tuttavia, la soluzione pubblicata da Brad Gilbert funziona anche poiché utilizza invece un handle di file esplicito.
Le tre righe all'inizio possono essere sostituite da:
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};
che chiude correttamente l'handle del file.