Hinweis: Ich habe meine Antwort als Antwort auf die Kommentare von @zostay und @ jm666 erweitert.
Der erste Schritt zu einer effizienten, klaren und prägnanten Antwort auf diese Frage beginnt mit der Idee, dass Variablen gehen in einem Aggregat . Also, das Array @fh
wird die Dateihandles enthalten, von denen wir gleichzeitig lesen.
Dann können wir eine Zeile aus jedem Dateihandle lesen und sie in einem Array unter Verwendung der <>
speichern Operator in Verbindung mit Karte . map
verwendet eine Transformationsregel und eine Liste und gibt eine andere Liste zurück. Daher:
nimmt die Dateihandles in @fh
und liest jeweils eine einzelne Zeile aus (Anmerkung Skalar ) und legt diese Zeilen in @lines
. Dies ist eine one-to-one
Transformation von @fh
.
Wie die Dokumentation für <>
angibt, gibt <>
einen nicht definierten Wert zurück, wenn das Dateiende erreicht ist oder ein Fehler aufgetreten ist.
Nun können Sie überprüfen, ob wir erfolgreich aus allen Dateien lesen können, indem Sie überprüfen, ob die Anzahl definierte Zeilen enthält ist die gleiche wie die Anzahl der Dateihandles. grep wählt Elemente einer Liste aus, die ein bestimmtes Kriterium erfüllen. Daher
%Vor% würde prüfen, ob die Anzahl der Dateihandles in @fh
mit der Anzahl der definierten Elemente in @lines
übereinstimmt. Allerdings kann das @fh
, das auf beiden Seiten dieses Vergleichs erscheint, in der Tat verwirrend sein, so dass eine alternative Methode zur Überprüfung der dort sind keine undefinierten Elemente in @lines
ist:
Wenn Sie diese Bedingung in eine Schleife während einfügen möchten, müssen Sie Folgendes schreiben:
%Vor%Wenn Sie jedoch mit bis fortfahren, können Sie einfach Folgendes schreiben:
%Vor%Dies bedeutet ", bis mindestens eine der Leselinien einen nicht definierten Wert zurückgibt, führen Sie den Körper der Schleife " aus.
Beachten Sie, dass Perls eof
anders ist als Cs eof
. Die Dokumentation für Perls eof
stellt Folgendes fest:
Praktischer Hinweis: Sie müssen fast nie
eof
in Perl verwenden, weil die Eingabeoperatoren normalerweiseundef
zurückgeben, wenn sie keine Daten mehr haben oder einen Fehler entdecken.
Wenn Sie eof
jedes Mal durch die Schleife überprüfen, verdoppeln Sie Ihr Datei-IO, weil " diese Funktion tatsächlich ein Zeichen liest und dann ungetc
s it ."
Ich gebe fast immer ein eigenständiges lauffähiges Beispiel mit meinem Code. Im Folgenden wollte ich nicht auf bestimmte Dateien auf Ihrem System zurückgreifen, daher verwende ich die immer verfügbaren DATA
und STDIN
Punkte. Im Gegensatz zur Verwendung der Funktion eof
müssen Sie sich bei der Verwendung dieser Methode keine Gedanken darüber machen, wo Sie gerade lesen: Sie müssen nur wissen, ob eine Readline in einer der Dateien einen nicht definierten Wert zurückgegeben hat. Es kann auch mit einer beliebigen Anzahl von Dateihandles verwendet werden. Außerdem haben Sie die Dateihandles wirklich nicht in ein Array eingefügt, aber wie gesagt, verwandte Variablen gehören zu einem Aggregat, wenn Sie also Dinge wie
beachte, dass du ein Array benutzt haben solltest, um die Dateihandles zu speichern .
%Vor% Dieses Beispielskript hört auf, nach Ihrer Eingabe in STDIN
zu fragen, wenn die Zeilen in DATA
erschöpft sind. Wenn Sie im Skript keine abschließenden Leerzeilen haben, müssen Sie vor dem Skriptende drei vier Zeilen eingeben.
Wenn Sie jetzt wissen möchten, welche Dateihandles das Ende erreicht haben, würden Sie zu etwas wie:
wechseln %Vor%Die obigen Schleifen sind so konzipiert, dass sie aufhören, wenn eine der Dateien erschöpft ist. Auf der anderen Seite möchten Sie möglicherweise, dass die Loops ausgeführt werden, bis alle Dateien erschöpft sind. In diesem Fall würden Sie verwenden:
%Vor% Eine andere einfache Lösung ohne explizite eof()
Prüfung würde folgendermaßen aussehen:
Dies nutzt die Tatsache, dass <>
undef
if & amp; nur wenn Sie am Ende der Datei sind.