Dies ist eher ein Vorschlag, wie man es NICHT macht. Ich hatte gerade eine schlechte Zeit, einen Fehler in einer ziemlich großen Perl-Anwendung zu finden. Die meisten Module hatten eigene Konfigurationsdateien. Um die Konfigurationsdateien als Ganzes zu lesen, habe ich diese einzelne Perl-Zeile irgendwo im Internet gefunden:
# Bad! Don't do that!
my $content = do{local(@ARGV,$/)=$filename;<>};
Der Zeilentrenner wird wie zuvor erläutert neu zugewiesen. Es ordnet aber auch den STDIN neu zu.
Dies hatte mindestens einen Nebeneffekt, dessen Suche mich Stunden gekostet hat: Das implizite Dateihandle wird nicht ordnungsgemäß geschlossen (da es überhaupt nicht aufgerufen wird close
).
Zum Beispiel:
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";
Ergebnisse 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
Das Seltsame ist, dass der Zeilenzähler $.
für jede Datei um eins erhöht wird. Es wird nicht zurückgesetzt und enthält nicht die Anzahl der Zeilen. Und es wird beim Öffnen einer anderen Datei nicht auf Null zurückgesetzt, bis mindestens eine Zeile gelesen wurde. In meinem Fall habe ich so etwas gemacht:
while($. < $skipLines) {<FILE>};
Aufgrund dieses Problems war die Bedingung falsch, da der Zeilenzähler nicht ordnungsgemäß zurückgesetzt wurde. Ich weiß nicht, ob dies ein Fehler oder einfach ein falscher Code ist ... Auch das Aufrufen von close;
oder close STDIN;
hilft nicht.
Ich habe diesen unlesbaren Code durch Öffnen, Verketten von Zeichenfolgen und Schließen ersetzt. Die von Brad Gilbert veröffentlichte Lösung funktioniert jedoch auch, da stattdessen ein explizites Dateihandle verwendet wird.
Die drei Zeilen am Anfang können ersetzt werden durch:
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};
Dadurch wird das Dateihandle ordnungsgemäß geschlossen.