ubuntuusers.de

Python lernen: Textfile nach Inhalt sortieren

Status: Gelöst | Ubuntu-Version: Kubuntu 20.04 (Focal Fossa)
Antworten |

michahe

Anmeldungsdatum:
12. Dezember 2013

Beiträge: 857

Hallo,

ich habe txt-Files mit folgendem Schema:

  • 3 .. n Zeilen (CTRL-N als Zeilentrenner),

  • die Zeilen 1 und 2 sind Überschriften und sollen als Zeilen 1 und 2 in die sortierte Ergebnis-Datei geschrieben werden.

  • Die Zeilen 3 bis n enthalten Werte für Spalten, die mit | getrennt sind;

  • in jeder dieser Werte-Zeilen ist in Spalte 2 ein Datum und in Spalte 3 eine Uhrzeit.

Beispiel

Erläuterung xxx|20.08.2021|08:36|Spalte 4|Spalte5|...

Ich möchte eine Datei einlesen und sortiert nach Datum plus Uhrzeit ausgeben. Schubst mich bitte jemand in die richtige Richtung?

Danke, Michael

ChickenLipsRfun2eat Team-Icon

Anmeldungsdatum:
6. Dezember 2009

Beiträge: 12067

<schubs>

Was genau brauchst du denn für einen Schubs? Wenn die Zeilen per newline getrennt sind und die Daten zeilenweise, dann liest du die Datei zeilenweise aus und zerlegst diese mit string.split und dem Trennzeichen Pipe (|).

Du könntest auch funktionen basteln, die nur die Überschriften enthalten oder sowas. Ich meine in Python nennt sich das Tuple. Dann kannst du per tuple.datum, tuple.header1, tuple.header2 und tuple.description nach Lust und Laune sortieren.

michahe

(Themenstarter)

Anmeldungsdatum:
12. Dezember 2013

Beiträge: 857

Danke ChickenLipsRfun2eat,

<schubs> Was genau brauchst du denn für einen Schubs?

Ich habe wieder einmal das Problem, dass es viele Anleitungen gibt, aber viele auch nicht funktionieren. Z.B.

file_ergebnis="Dateiname.txt"
txt = open(file_ergebnis, "r")

sagt nichts über die Zeilennummer oder die Anzahl der Zeilen.

fleet_street

Top-Wikiautor
Avatar von fleet_street

Anmeldungsdatum:
30. August 2016

Beiträge: 2400

Wohnort: Hunsrück (dunkle Seite)

… dass es viele Anleitungen gibt, aber viele auch nicht funktionieren.

So ist das ganz schön schwammig. Konkrete Frage sieht anders aus. 😉 Sind die vielleicht noch für Python 2?

… sagt nichts über die Zeilennummer oder die Anzahl der Zeilen.

Bis dahin hast du auch nur ein Dateiobjekt (lesend) zugewiesen, aber noch nichts weiter.

Ich habe mit dem (gedruckten) Buch Python 3 angefangen, das man auch online frei lesen kann:
6.2 Daten aus einer Datei auslesen

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11261

Wohnort: München

So grob:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env python3
import sys
from datetime import datetime

with open('datei.txt') as f, open('ergebnis.txt', 'w') as output:
    # read two header lines
    try:
        header = next(f), next(f)
    except StopIteration:
        sys.exit('Error: file has less than two lines')
    content = []
    for line in f:
        if not (l := line.rstrip()):
            continue
        _, date, time, *_ = l.split('|')

        date = datetime.strptime(f"{date} {time}", "%d.%m.%Y %H:%M")
        content.append((date, line))
    print(*header, sep='', end='', file=output)
    print(*(l for _, l in sorted(content)), sep='', end='', file=output)

Edit: da habe ich doch glatt das Sortieren vergessen...

noisefloor Team-Icon

Anmeldungsdatum:
6. Juni 2006

Beiträge: 29567

Hallo,

@michahe: wenn du einen Einfluss auf das Format der Text-Datei hast, dann schreib' Datum und Uhrzeit als Zeitstempel zusammen, das macht einiges einfacher.

Wenn man das Sortieren nicht von Hand machen möchte bietet sich noch stark das pandas-Modul an. Der Suchbegriff python sort csv by two columns by Google liefert reichlich Beispiele dafür.

Gruß, noisefloor

michahe

(Themenstarter)

Anmeldungsdatum:
12. Dezember 2013

Beiträge: 857

Danke seahawk1986,

super! Funktioniert perfekt, ich hatte nur (im Gegensatz zu meiner Beschreibung) die Zeit im Format hh:mm:ss und habe die Code-Zeile 17 entsprechend angepasst. Magst Du mir noch etwas Erläuterung zu den Codezeile 13 .. 15 geben, damit ich weiter lerne?

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11261

Wohnort: München

michahe schrieb:

Danke seahawk1986,

super! Funktioniert perfekt, ich hatte nur (im Gegensatz zu meiner Beschreibung) die Zeit im Format hh:mm:ss und habe die Code-Zeile 17 entsprechend angepasst. Magst Du mir noch etwas Erläuterung zu den Codezeile 13 .. 15 geben, damit ich weiter lerne?

f ist ein file-like Objekt, das einen Iterator implementiert, der die einzelnen Zeilen der Datei ausspuckt. Zeile 13 prüft, ob die aktuell verarbeitete Zeile etwas anderes außer dem Zeilenende enthält - ein leerer String wird im if-Statement als False gewertet - da Dateien mit einem Zeilenumbruch enden können und in dem Fall überspringt er die Zeile. := ist ein Assignment Operator (vgl. z.B. https://realpython.com/lessons/assignment-expressions/), der es erlaubt gleichzeitig einer Variable einen Wert zuzuweisen und diesen zu evaluieren - in der Langform könnte man das so schreiben:

1
2
3
        l = line.rstrip()
        if not l:
            continue

Und in Zeile 15 wird mittels _, date, time, *_ = l.split('|') der String an den Pipe-Zeichen aufgetrennt und dann erfolgt eine Zuweisung der Werte zu Variablen. Der Unterstrich wird in Python-Code gerne benutzt, um zu signalisieren, dass einen der Wert nicht interessiert. Wir ignorieren also das erste Element aus der Liste, dann wird das zweite Element der Variablen date zugewiesen, das dritter der Variablen time und der Rest wird durch *_ eingesammelt.

Alternativ könnte man das z.B. auch so schreiben - aber über einen Slice einer Liste zu gehen klappt nur, wenn man einen nur benachbarte Werte interessieren (und maxsplit kann man nutzen, um sich Arbeit beim Zerlegen der Felder zu sparen):

1
date, time = l.split('|', maxsplit=4)[1:3]

michahe

(Themenstarter)

Anmeldungsdatum:
12. Dezember 2013

Beiträge: 857

Danke seahawk1986 für die perfekte Lösung und die gute, ausführliche Erklärung.

Antworten |