Philipp Hasenfratz: Ressourcenschonend die letzten 10 Zeilen einer Textdatei ausg.

Beitrag lesen

Halihallo Forumer

Der Modulo-Operator ([pref:t=52959&m=292762]) hat noch mehr Anwendungsgebiete:
Ich habe mir gerade überlegt, wie man dies a) möglichst performant und b)
speicherschonend umsetzen kann. Hierzu habe ich ein kleines Script geschrieben.

Ich habe zwar noch keine Benchmarks durchgeführt, würde jedoch behaupten, dass es _nicht_
schneller ist (da in Perl; das splicing von Arrays alla @data[-10,-1] geschieht
wesentlich schneller), aber wesentlich weniger Ressourcen verschwendet (je grösser die
Datei desto weniger).

Ich hätte noch einige Performance-Algorithmen, die auch wenig Speicher verschwenden,
wollte es aber mal über einen Modulo-Algo. machen, da dieser mich inspiriert hat :-)

Das Grundprinzip:
Es soll _nicht_ die ganze Datei in ein Array gepackt werden!

Also? -> Zeilenweises auslesen, aber wie kriegt man die letzten 10 Zeilen? - Wir brauchen
eine Art Cache, der die letzten 10 Zeilen speichert. Nur: die letzten Zeilen müssen immer
aus dem Cache rausgeschmissen werden (ein splice _verdoppelt_ die Datenmenge und braucht
auch viel Zeit, was zwar bei kleinen Arrays nicht ins Gewicht fällt, aber was, wenn wir
die letzten 100000 Zeilen wollen?). Tja, hier kommt der Modulo in Einsatz; der Trick
ist, dass die 1 Zeile eben _nicht_ den ersten Array-Index trägt, sondern variabel ist
und einfach die "letzte" Zeile überschreibt (somit brauchen wir den splice nicht mehr).
Tja, dann haben wir aber eine "ungeordnetes" Array, also müssen wir es mit einer for-
Schleife wieder in Ordnung bringen.

Mal sehen, was ihr dazu meint; besonders würde es mich interessieren, wenn jemand eine
bessere Lösung hat (ich weiss nie eine gute, praktikable Antwort auf diese Frage "last
10 lines..."). Hm, im Perl Cookbook steht auch ein Beispiel, soweit ich mich erinnere,
nur habe ich es im Moment nicht vorliegen.

#!/usr/bin/perl

use strict;

my $last_lines_count = 10; # Anzahl Linien
my @last_lines = ();  # Array mit letzten linien, temporär!

$#$last_lines = $last_lines_count-1;

Bei grossen Arrays kann dies gut Zeit sparen. Grösse des Arrays vordefiniert.

my $cnt = 0;   # aktuelle Zeile
open( F, '<./file.txt' ) || die "cannot open: $!";
while (<F>) {
   chomp;   # Zeilenumbruch abscheiden, falls vorhanden.
   $last_lines[$cnt % ($last_lines_count)] = $_;
   # der Kern der Verbesserung: keine Verschiebung oder splice von Arrays nötig.
   $cnt++;   # nächste Zeile...
}
close F || die "cannot close: $!";

tja, @last_lines gibt die Zeilen nicht in der richtigen Reihenfolge aus, also

müssen wir dies anpassen:

for ( my $i=$cnt; $i < $cnt + $last_lines_count; $i++ ) {
   print $last_lines[$i % ($last_lines_count)] . "\n";
}

Viele Grüsse

Philipp

--
RTFM! - Foren steigern das Aufkommen von Redundanz im Internet, danke für das lesen der Manuals.
Selbstbedienung! - Das SelfForum ist ein Gratis-Restaurant mit Selbstbedienung, Menüangebot steht in den </faq/> und dem </archiv/>.