Logdatei (Textfile) filtern und sortieren

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
power74
User
Beiträge: 14
Registriert: Donnerstag 3. September 2015, 12:25
Wohnort: in der Nähe von Zürich

Hallo Forum

Ich habe eine Logdatei (derzeit ca. 50MB) die ich gerne auswerten möchte.
Die Logzeilen sehen in etwa so aus:

Code: Alles auswählen

2017-01-29 22:11:21: ACTION[Server]: ABC.....(Text bis ans Ende der Zeile)
2017-01-29 22:12:37: ACTION[Server]: Lor.....(Text bis ans Ende der Zeile)
2017-01-29 22:14:31: ACTION[Server]: ABC.....(Text bis ans Ende der Zeile)
2017-01-29 22:14:24: ACTION[Server]: ABC.....(Text bis ans Ende der Zeile)
2017-01-29 22:16:11: ACTION[Server]: Lor.....(Text bis ans Ende der Zeile)
2017-01-29 22:18:27: ACTION[Server]: 7Zbb.....(Text bis ans Ende der Zeile)
Die Idee ist, dass erstens nach den Zeichen nach [Server]: sortiert wird (also ABC,Lor,7Zbb) und als zweites Kriterium nach dem Datum/der Zeit.
Das Problem ist, dass die Zeichen nach dem Wort [Server]: beliebig sein können. Dort stehen unvorhersehbare Fantasienamen.
Die sortierte Datei sollte in einer neuen Textdatei ausgegeben werden.

Ist das überhaupt lösbar?
AttributeError: 'power74' object has no attribute 'nervenbehalten'
BlackJack

@power74: Ja das ist möglich. Die `sort()`-Methode auf Listen oder die `sorted()`-Funktion kennen dafür das `key`-Argument das eine Funktion oder Methode erwartet die ein Element als Argument bekommt und den Wert nach dem sortiert werden soll als Ergebnis liefern muss. Also in diesem Fall zum Beispiel ein Tupel aus der Zeichenkette und dem Datum.
Benutzeravatar
power74
User
Beiträge: 14
Registriert: Donnerstag 3. September 2015, 12:25
Wohnort: in der Nähe von Zürich

OK aber wie schreibe ich im Code, dass das Wort nach ACTION[Server]: so ein Schlüsselwort für die Sortierung ist.

Könntest du bitte anhand der Logbeispiele zeigen, wie so ein Code aussehen müsste, der nach beliebigen (noch nicht bekannten) Begriffen sortieren kann (nebst dem Datum)? Vom Konzept her müsste man doch erst mal alle diese Begriffe einlesen und dann die Zeilen mit demselben Begriff gruppieren und dann innerhalb dieser Gruppe noch nach Datum/Zeit sortieren. Oder denke ich da noch um sieben Ecken rum?

Ungefähr so schwebt mir das im Kopf rum aber ich als "Hochseedampfunterseebootkapitänsgehilfe" :) habe damit erhebliche Mühe sowas aufs Papier/den Bildschirm zu kriegen, sorry... ich hab' noch zu wenig Übung mit programmieren.
Der zu beachtende Begriff beginnt nach dem Leerzeichen nach [Server]: und endet vor dem nächsten Leerzeichen - so würde ich das umgangssprachlich definieren.

Natürlich kannst du argumentieren, dass ich die von dir genannten Ansätze erst mal studieren soll (hast recht ja, sollte ich) - aber dann muss ichs wohl auf die nächsten Ferien verschieben... daher meine Bitte.
AttributeError: 'power74' object has no attribute 'nervenbehalten'
BlackJack

@power74: Du brauchst nur eine Funktion die *eine* Zeile in ein Tupel überführt mit den Werten nach denen sortiert werden soll in der Reihenfolge in der sortiert werden soll. Die Funktion übergibst Du `sort()` oder `sorted()`, die machen dann den ganzen Rest. Wie kompliziert die Funktion wird, hängt davon ab wie die Logdatei tatsächlich aussieht. Also was fest und was variabel ist.

Code: Alles auswählen

In [10]: line
Out[10]: '2017-01-29 22:11:21: ACTION[Server]: ABC.....(Text bis ans Ende der Zeile)'

In [11]: line.partition(': ACTION[Server]: ')
Out[11]: 
('2017-01-29 22:11:21',
 ': ACTION[Server]: ',
 'ABC.....(Text bis ans Ende der Zeile)')

In [12]: timestamp, _, text = line.partition(': ACTION[Server]: ')

In [13]: (text, timestamp)
Out[13]: ('ABC.....(Text bis ans Ende der Zeile)', '2017-01-29 22:11:21')
Und ich bin mir nach der Beschreibung nicht ganz sicher ob die gesamte Restzeile, oder nur ein Präfix davon und wenn ja nach welchen Kriterium dieser Präfix gewählt werden soll.
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

Wenn der beliebige Text keine Leerzeichen enthält, könnte das im einfachsten Fall vielleicht so aussehen:

Code: Alles auswählen

#!/usr/bin/env python3
from operator import itemgetter
 
def main():
    with open('log.txt', 'r') as fh:
        lines = [line.split() for line in fh]
    for line in sorted(lines, key=itemgetter(0,1,4)):
        print(' '.join(line))

if __name__ == '__main__':
    main()

Code: Alles auswählen

$ cat log.txt
2017-01-29 22:18:27: ACTION[Server]: 7Zbb Lorem_Ispum
2017-01-29 22:14:24: ACTION[Server]: ABC Lorem_Ispum
2017-01-29 22:11:21: ACTION[Server]: ABC Lorem_Ispum
2017-01-29 22:12:37: ACTION[Server]: Lor Lorem_Ispum
2017-01-29 22:14:31: ACTION[Server]: ABC Lorem_Ispum
2017-01-29 22:16:11: ACTION[Server]: Lor Lorem_Ispum

$ ./test.py  
2017-01-29 22:11:21: ACTION[Server]: ABC Lorem_Ispum
2017-01-29 22:12:37: ACTION[Server]: Lor Lorem_Ispum
2017-01-29 22:14:24: ACTION[Server]: ABC Lorem_Ispum
2017-01-29 22:14:31: ACTION[Server]: ABC Lorem_Ispum
2017-01-29 22:16:11: ACTION[Server]: Lor Lorem_Ispum
2017-01-29 22:18:27: ACTION[Server]: 7Zbb Lorem_Ispum
Wenn die Datei komplizierter ist, könnte man auch reguläre Ausdrücke verwenden. Auch das Zusammenfügen der Zeilen sähe dann natürlich anders aus, und kann ggf. so umgegangen werden, dass man sich die Originalzeilen in einem Dictionary merkt.
BlackJack

@nezzcarth: Einer von uns beiden hat die Sortierkriterien falsch verstanden. Ich hatte das so verstanden das erst nach dem Text(präfix) und dann nach dem Zeitstempel sortiert werden soll, denn erst nach Datum und dann nach Textpräfix würde kein `key` benötigen, da kann man auch ganz normal die Zeilen sortieren lassen.

Ich hatte es so verstanden dass das Ergebnis so aussehen sollte:
[codebox=text file=Unbenannt.txt]2017-01-29 22:18:27: ACTION[Server]: 7Zbb.....(Text bis ans Ende der Zeile)
2017-01-29 22:11:21: ACTION[Server]: ABC.....(Text bis ans Ende der Zeile)
2017-01-29 22:14:24: ACTION[Server]: ABC.....(Text bis ans Ende der Zeile)
2017-01-29 22:14:31: ACTION[Server]: ABC.....(Text bis ans Ende der Zeile)
2017-01-29 22:12:37: ACTION[Server]: Lor.....(Text bis ans Ende der Zeile)
2017-01-29 22:16:11: ACTION[Server]: Lor.....(Text bis ans Ende der Zeile)[/code]
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

BlackJack hat geschrieben:@nezzcarth: Einer von uns beiden hat die Sortierkriterien falsch verstanden.
Ich glaube, ich :oops: Dein Ergebnis könnte man, wenn ich es richtig sehe, doch erreichen, in dem man in meinem Beispiel itemgetter andere Parameter gibt (itemgetter(3, 0, 1)), oder?
BlackJack

@nezzcarth: Jup, das sollte gehen.
Benutzeravatar
power74
User
Beiträge: 14
Registriert: Donnerstag 3. September 2015, 12:25
Wohnort: in der Nähe von Zürich

Vielen Dank,

variabel ist alles was nach ACTION[SERVER]: kommt. Sortiert werden sollte als erstes nach dem Wort (ohne Leerzeichen) nach [SERVER]: und erst dann nach Datum/Zeit. Es soll dann aber immer die ganze Zeile (inkl. dem Text mit allen Leerzeichen) in die neue Datei kopiert und sortiert werden.

:?: Seid ihr noch immer derselben Meinung?
AttributeError: 'power74' object has no attribute 'nervenbehalten'
BlackJack

@power74: Im Grunde ja. ``[Server]`` hatte bis jetzt noch niemand auf dem Schirm weil da nicht wirklich ersichtlich war ob das Variabel ist und falls ja ob es irgendwie ins Ergebnis einfliessen sollte. Das Prinzip bleibt aber das gleiche.
Antworten