Forum: PC-Programmierung Regex zum Verzweifeln.


von SimonU (Gast)


Lesenswert?

Hallo,

ich probiere jetzt seit 5 Stunden herum und komme einfach nicht weiter. 
Programmiersprache ist Python.

Es gibt Logdateien mit unbestimmer Anzahl an Einträgen.

1
1300105811    Datei7    test0    test10   
2
1300107321    Datei7    test1    test9   
3
1300108129    Datei7    test2    test8   
4
1300107162    Datei7    test3    test7   
5
1300105515    Datei7    test4    test6   
6
1300106386    Datei7    test5    test5   
7
1300106818    Datei7    test6    test4   
8
1300106542    Datei7    test7    test3   
9
1300106770    Datei7    test8    test2   
10
1300105745    Datei7    test9    test1

Die sehen alle in etwa so aus. Grundsätzlich ist der Aufbau so, dass
es verschiedene Felder gibt, die durch \t getrennt sind. Wenn ein neuer 
Eintrag kommt, erkennt man das an \t\n. Es ist möglich, dass ein Eintrag 
sich über mehrere Zeilen erstreckt. Das heißt, dass in einem Eintrag in 
einem Feld ein \n vorkommen kann. Das kann jedoch niemals am Anfang 
eines Feldes geschehen.

So, mein Problem ist jetzt das Auslesen dieser Datei.

Meine Versuche reichen von
1
compiled_regex = re.compile(r"(([^\t]+?\t)+?\n)+?", re.MULTILINE)

über
1
compiled_regex = re.compile(r"((\S+?\t)+?\n)+?", re.MULTILINE)

usw...

Keine der Versionen funktioniert wie erwartet! Ich erhalte immer nur ein 
Feld zurück, außer ich mache das so:
1
compiled_regex = re.compile(r"((\S+?\t)(\S+?\t)\n)+?", re.MULTILINE)

Dann erhalte ich zwei Felder.

Die Anzahl der Felder ist aber dynamisch! Ich suche also einen Regex, 
mit dem ich ALLE Felder (zw. 1 und 50) in ALLEN Einträgen ermitteln 
kann.

ich komme jedenfalls nicht mehr weiter.

Habt ihr eine Idee?

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Mach es in zwei Schritten:
1. Datei an \t\n in Zeilen aufsplitten
2. jede Zeile an \t in Spalten aufsplitten

Beispiel in Ruby (kannst du sicher einfach in Python umsetzen):
1
s = "1\t2\t3\t\n1\t2\t\n"
2
zeilen  = s.split(/\t\n/)
3
felder = zeilen.map do |zeile|
4
  zeile.split(/\t/)
5
end
6
7
puts felder.inspect

=> [["1", "2", "3"], ["1", "2"]]

von SimonU (Gast)


Lesenswert?

Das wäre natürlich möglich. Da ich aber sehr sehr viele Logeinträge 
habe, muss ich auf Performance achten (Dateien sind teils über 10MB 
groß).

Ist es komplett unmöglich, das in einem Regex zu machen?

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Wieso meinst du dass das mit einer Regex schneller gehen wird? Bei 
verschachtelten Ausdrücken ist nur die Wahrscheinlichkeit höher dass du 
dir einen Speicher- und Rechenzeitfresser mit exponentieller Komplexität 
baust.

Und spielt Rechenzeit überhaupt eine Rolle? 10 MB ist doch nichts.

von Peter II (Gast)


Lesenswert?

SimonU schrieb:
> Dateien sind teils über 10MB groß
wahnsinn, und da machst du dir gedanken? Bei mir fängt groß zur zeit bei 
1GB an.

von SimonU (Gast)


Lesenswert?

Es sind jeweils ca. 50 Dateien pro Skriptdurchlauf. Also 500MB könnten 
da schon zusammenkommen.

Ich werde es jetzt so lösen (2 Schritte), bis ich eine Lösung mit nur 
einem regulären Ausdruck habe. Das war auch die Vorgabe an das Programm 
(vom Chef)

von SimonU (Gast)


Lesenswert?

läuft

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

SimonU schrieb:
> bis ich eine Lösung mit nur
> einem regulären Ausdruck habe
Oh man... was soll das bringen? nur weil der "Chef" das sagt?

SimonU schrieb:
> ich probiere jetzt seit 5 Stunden herum
Stattdessen nochmal ein paar Stunden "rumprobieren"... wiviele Millarden 
Jahre soll den das Skript sich im EInsatz befinde das es die (noch 
nichtmal nachgewiesene) Geschwindigkeitssteigerung wieder reinholt die 
man durch solche "Optimierungen" verbrät?
Gerade bei großen Dateien kann es sich lohne die Datei Zeilenweise 
einzulesen, da hierdurch nicht erst die ganze Datei in den Speicher 
geladen werden muss.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.