Wie man variable Räume in jeder Zeile einer Textdatei auf der Grundlage einer speziellen Bedingung – Ein-Liner in Python?

Ich habe einige Daten (Textdateien), die in der meisten unebenen Weise formatiert werden, die man sich vorstellen kann. Ich versuche, die Anzahl der manuellen Arbeiten beim Analysieren dieser Daten zu minimieren.

Beispieldaten :

  • Apt wie Spalte Ausgabe - Python-Bibliothek
  • Tausende Trennzeichen in iPython ohne String-Formatierung setzen
  • Formatieren Sie die Telefonnummer in csv mit Pandas
  • Benutzerfreundliches Zeitformat in Python?
  • Setzen Sie das Openpyxl-Zellenformat in die Währung
  • Wie man variable Anzahl von Elementen mit sep und end ausdruckt?
  • Name Degree CLASS CODE EDU Scores -------------------------------------------------------------------------------------- John Marshall CSC 78659944 89989 BE 900 Think Code DB I10 MSC 87782 1231 MS 878 Mary 200 Jones CIVIL 98993483 32985 BE 898 John G. S Mech 7653 54 MS 65 Silent Ghost Python Ninja 788505 88448 MS Comp 887 

    Bedingungen:

    • Mehr als ein Leerzeichen sollte zu einem Trennzeichen komprimiert werden (Rohr besser? Ende Ziel ist es, diese Dateien in der Datenbank zu speichern).
    • Mit Ausnahme der ersten Spalte haben die anderen Spalten keine Leerzeichen in ihnen, so dass alle diese Räume zu einer Pipe komprimiert werden können.
    • Nur die erste Spalte kann mehrere Wörter mit Leerzeichen haben (Mary K Jones). Der Rest der Spalten sind meist Zahlen und einige Alphabete.
    • Erste und zweite Spalten sind beide Saiten. Sie haben fast immer mehr als eine Leerzeichen zwischen ihnen, so können wir zwischen den 2 Spalten unterscheiden. (Wenn es einen einzigen Raum gibt, ist das ein Risiko, das ich bereit bin, die schreckliche Formatierung zu nehmen!).
    • Die Anzahl der Spalten variiert, so dass wir uns keine Sorgen um Spaltennamen machen müssen. Alles was wir wollen, ist, die Daten der einzelnen Spalten zu extrahieren.

    Hoffe ich habe Sinn gemacht! Ich habe das Gefühl, dass diese Aufgabe in einem Oneliner durchgeführt werden kann. Ich möchte nicht Schleife, Schleife, Schleife 🙁

    Muchos gracias "Pythonistas" für das Lesen des ganzen Weges und nicht vor diesem Satz beenden!

    3 Solutions collect form web for “Wie man variable Räume in jeder Zeile einer Textdatei auf der Grundlage einer speziellen Bedingung – Ein-Liner in Python?”

    Es scheint immer noch, dass es ein Format in deinen Dateien gibt:

     >>> regex = r'^(.+)\b\s{2,}\b(.+)\s+(\d+)\s+(\d+)\s+(.+)\s+(\d+)' >>> for line in s.splitlines(): lst = [i.strip() for j in re.findall(regex, line) for i in j if j] print(lst) [] [] ['John Marshall', 'CSC', '78659944', '89989', 'BE', '900'] ['Think Code DB I10', 'MSC', '87782', '1231', 'MS', '878'] ['Mary 200 Jones', 'CIVIL', '98993483', '32985', 'BE', '898'] ['John G. S', 'Mech', '7653', '54', 'MS', '65'] ['Silent Ghost', 'Python Ninja', '788505', '88448', 'MS Comp', '887'] 

    Regex ist ganz einfach, die einzigen Dinge, die Sie beachten müssen, sind die Begrenzer ( \s ) und das Wort bricht ( \b ) im Falle des ersten Trennzeichens. Beachten Sie, dass, wenn die Zeile nicht übereinstimmt, Sie eine leere Liste als lst . Das wäre ein Lese-Flag, um die unten beschriebene Benutzerinteraktion aufzurufen. Auch kannst du die Kopfzeilen überspringen, indem du:

     >>> file = open(fname) >>> [next(file) for _ in range(2)] >>> for line in file: ... # here empty lst indicates issues with regex 

    Vorherige Varianten:

     >>> import re >>> for line in open(fname): lst = re.split(r'\s{2,}', line) l = len(lst) if l in (2,3): lst[l-1:] = lst[l-1].split() print(lst) ['Name', 'Degree', 'CLASS', 'CODE', 'EDU', 'Scores'] ['--------------------------------------------------------------------------------------'] ['John Marshall', 'CSC', '78659944', '89989', 'BE', '900'] ['Think Code DB I10', 'MSC', '87782', '1231', 'MS', '878'] ['Mary 200 Jones', 'CIVIL', '98993483', '32985', 'BE', '898'] ['John G. S', 'Mech', '7653', '54', 'MS', '65'] 

    Eine andere Sache zu tun ist einfach erlauben Benutzer zu entscheiden, was mit fragwürdigen Einträgen zu tun:

     if l < 3: lst = line.split() print(lst) iname = input('enter indexes that for elements of name: ') # use raw_input in py2k idegr = input('enter indexes that for elements of degree: ') 

    Uhm, ich war die ganze Zeit unter dem Eindruck, dass das zweite Element Leerzeichen enthalten könnte, denn es ist nicht so, dass du es einfach tun könntest:

     >>> for line in open(fname): name, _, rest = line.partition(' ') lst = [name] + rest.split() print(lst) 

    Variation auf SilentGhost's Antwort, diesmal zuerst den Namen von dem Rest (getrennt durch zwei oder mehr Räume), dann nur die Aufteilung der Rest, und schließlich eine Liste.

     import re for line in open(fname): name, rest = re.split('\s{2,}', line, maxsplit=1) print [name] + rest.split() 

    Diese Antwort wurde geschrieben, nachdem der OP gestanden hatte, jeden Tab ("\ t") in seinen Daten auf 3 Räume zu ändern (und nicht in seiner Frage zu erwähnen).

    Betrachtet man die erste Zeile, so scheint es, dass dies ein Bericht mit fester Spalte ist. Es ist durchaus möglich, dass Ihre Daten Tabs enthalten, die, wenn sie richtig erweitert wurden, zu einem nicht-verrückten Ergebnis führen könnten.

    Anstatt line.replace('\t', ' ' * 3) tun line.replace('\t', ' ' * 3) line.expandtabs() .

    Docs für expandtabs sind hier

    Wenn das Ergebnis sinnvoll aussieht (Spalten der Datenleitung), müssen Sie bestimmen, wie Sie die Spaltenbreiten programmatisch ausführen können (falls dies möglich ist) – vielleicht aus der Überschrift.

    Bist du sicher, dass die zweite Zeile alle "-" ist oder gibt es Zwischenräume zwischen den Spalten? Der Grund für die Frage ist, dass ich einmal musste viele verschiedene Dateien aus einem Datenbank-Abfrage-Bericht-Mechanismus, die die Ergebnisse wie folgt präsentiert zu analysieren:

     RecordType ID1 ID2 Description ----------- -------------------- ----------- ---------------------- 1 12345678 123456 Widget 4 87654321 654321 Gizmoid 

    Und es war möglich, einen völlig allgemeinen Leser zu schreiben, der die zweite Zeile untersuchte, um zu bestimmen, wo die Überschriftlinie und die Datenleitungen geschnitten werden sollen. Hinweis:

     sizes = map(len, dash_line.split()) 

    Wenn expandtabs () nicht funktioniert, bearbeite deine Frage, um genau zu zeigen, was du hast, dh das Ergebnis von print repr(line) für die ersten 5 oder so Zeilen (einschließlich der Überschrift) zu zeigen. Es könnte auch nützlich sein, wenn man sagen könnte, welche Software diese Dateien produziert.

    Python ist die beste Programmiersprache der Welt.