Durchlaufen einer foreach-Schleife
Siechfred
- perl
Guten Tag allerseits,
mein Script liest aus einer Textdatei die Zeilen in ein Array. Nun sollen aus dem Array alle alten Einträge gelöscht werden. Mein Plan sieht so aus:
my $n = 0;
foreach(@zeilen) {
($ip, $zeit) = split(/|/, $_); # "|" ist das Trennzeichen
if($aktuelle_zeit - $zeit > $zeitabstand * 60) {
splice(@zeilen, $n, 1);
}
$n++;
}
Beißt sich da die berühmte Katze in den Schwanz, da ich ja während das (oder der?) Array durchlaufen wird, Elemente daraus lösche, oder ist o.g. Codeschnipsel "unbedenklich"? Oder habt ihr einen Tipp, wie man das selbe besser lösen kann?
mfg Torsten
Halihallo Siechfred
Beißt sich da die berühmte Katze in den Schwanz, da ich ja während das (oder der?) Array durchlaufen wird, Elemente daraus lösche, oder ist o.g. Codeschnipsel "unbedenklich"? Oder habt ihr einen Tipp, wie man das selbe besser lösen kann?
Nun ja, ein foreach mit splice ist böse, das steht auch irgendwo in der Doku. Aber:
a) warum liest du überhaupt die ganze Datei in ein Array ein? - Dateien liest man
Zeilenweise aus, dann musst du nur noch die relevanten Daten der Datei in einem
Array speichern und die Datei danach damit überschreiben.
b) Wenn ich mich deines Vorhabens nicht sehr täusche, sind die Daten bereits in nach
Zeit sortierter Form in der Datei. Das Problem würde sich auf das Auffinden des
jüngsten noch passenden Eintrages reduzieren, ab welchem die Daten eingelesen werden
müssen (das wäre dann eine for-Schleife mit if Abfrage, wo du den entsprechenden
Index im Array findest).
Viele Grüsse
Philipp
Hallo Philipp,
Nun ja, ein foreach mit splice ist böse, das steht auch irgendwo in der Doku.
Dann lasse ich es besser.
a) warum liest du überhaupt die ganze Datei in ein Array ein? - Dateien liest man
Zeilenweise aus [...]
Man lernt halt nie aus ;-)
b) Das Problem würde sich auf das Auffinden des jüngsten noch passenden Eintrages reduzieren [...]
Jo, schlauer Plan! Werde ich probieren. Manchmal braucht man halt ein paar Denkanstöße von außen.
mfg Torsten
Hallo Philipp,
also ich versuche es jetzt mal so (sitze im Büro und warte auf meinen nächsten Termin, der sich etwas verspätet, deshalb diese Art von Trockenübung):
open(LOGFILE, "+>datei") or die $!;
while(<LOGFILE>) {
($ip, $zeit) = split(/|/, $_);
if($aktuelle_zeit - $zeit > $zeitabstand * 60) {
push(@neue_zeilen, $_);
}
}
print LOGFILE @neue_zeilen;
close(LOGFILE);
Meintest du das so?
mfg Torsten
Halihallo Torsten
Meintest du das so?
Genau so...
Appropos zeilenweise auslesen: Gehört halt zur "guten Art", da wesentlich weniger
Ressourcen verschwendet werden (besonders bei dir, wo du nur ganz spezielle Daten
extrahieren möchtest).
Viele Grüsse
Philipp
use Mosche;
Nun ja, ein foreach mit splice ist böse, das steht auch irgendwo in der Doku. Aber:
Nöö. Das eigentliche Problem entsteht woanders.
Wenn du foreach benutzt, wird eine neue Liste erzeugt - es wird also über eine Kopie deiner Liste iteriert. Daher ist es auch nicht "schlimm", wenn du dann das Original irgendwie veränderst. (Wenn du einen dementsprechenen Code findest, der da irgendwie einen Fehler findet (allerdings mit while), kannst du ihn IMHO an perl5porters oder so schicken und etwas gewinne :-)).
Aber: Es werden hier die Indize mitgezählt. Wenn ein Element gelöscht wird, rutschen alle anderen eins auf => deine "Nummerierung" stimmt nicht mehr.
use Tschoe qw(Matti);
Guten Abend,
vielen Dank an Philipp und Matti, funktioniert prächtig :-)
mfg Torsten