Entfernen von duplizierten Zeilen aus einer txt-Datei

Ich verarbeite große Textdateien (~ 20MB) mit Daten, die durch Zeile begrenzt sind. Die meisten Dateneinträge werden dupliziert und ich möchte diese Duplikationen entfernen, um nur eine Kopie zu behalten.

Auch, um das Problem etwas komplizierter zu machen, werden einige Einträge mit einem zusätzlichen Bit von Informationen angehängt. In diesem Fall muss ich den Eintrag mit den Zusatzinformationen behalten und die älteren Versionen löschen.

  • Entfernen von In-Feld-Anführungszeichen in csv-Datei
  • Mehrere Regex-Ersetzungen basierend auf Listen in mehreren Dateien
  • So prüfen Sie, ob eine Liste von Zeichenfolgen in zwei separaten Dateien vorhanden ist
  • Beste Weg, um Wörter in Zahlen mit bestimmten Wortliste zu ändern
  • Vergleichen Sie eine .txt- und .csv-Datei und müssen mit dem passenden Namen in der .csv-Datei in .txt ersetzen
  • Awk-Befehle im Python-Skript
  • ZB muss ich daraus gehen:

     BOB 123 1DB
     JIM 456 3DB AX
     DAVE 789 1DB
     BOB 123 1DB
     JIM 456 3DB AX
     DAVE 789 1DB
     BOB 123 1DB EXTRA BITS
    

    Dazu:

     JIM 456 3DB AX
     DAVE 789 1DB
     BOB 123 1DB EXTRA BITS
    

    NB. Die endgültige bestellung ist egal

    Was ist ein effizienter Weg, dies zu tun?

    Ich kann awk, python oder irgendein Standard linux Kommandozeilen-Werkzeug verwenden.

    Vielen Dank.

  • Konvertieren Sie die Liste der Positionen [4, 1, 2] der beliebigen Länge zu einem Index für eine verschachtelte Liste
  • Wie kann man einen String mit einem gleichen Symbol auswerten?
  • Was ist der Unterschied zwischen eval, exec und kompilieren in Python?
  • Wie sicher ist die Auswertung mit eval?
  • Python - Zelle Buch verwendet eval (), ist es falsch?
  • Verwendung von eval in Python?
  • 8 Solutions collect form web for “Entfernen von duplizierten Zeilen aus einer txt-Datei”

    Wie wäre es mit dem folgenden (in Python):

     prev = None for line in sorted(open('file')): line = line.strip() if prev is not None and not line.startswith(prev): print prev prev = line if prev is not None: print prev 

    Wenn Sie eine Speicherauslastung ein Problem finden, können Sie die Sortierung als Vorverarbeitungsschritt mit der Unix- sort (die auf der Festplatte basiert ) und das Skript so ändern, dass sie die gesamte Datei nicht in den Speicher liest.

    awk '{x[$1 " " $2 " " $3] = $0} END {for (y in x) print x[y]}'

    Wenn Sie die Anzahl der Spalten für verschiedene Dateien angeben müssen:

     awk -v ncols=3 ' { key = ""; for (i=1; i<=ncols; i++) {key = key FS $i} if (length($0) > length(x[key])) {x[key] = $0} } END {for (y in x) print y "\t" x[y]} ' 

    Diese Variation auf glenn jackmans Antwort sollte unabhängig von der Position der Linien mit zusätzlichen Bits funktionieren:

     awk '{idx = $1 " " $2 " " $3; if (length($0) > length(x[idx])) x[idx] = $0} END {for (idx in x) print x[idx]}' inputfile 

    Oder

     awk -v ncols=3 ' { key = ""; for (i=1; i<=ncols; i++) {key = key FS $i} if (length($0) > length(x[key])) x[key] = $0 } END {for (y in x) print x[y]} ' inputfile 

    Diese oder eine kleine Variante sollte:

     finalData = {} for line in input: parts = line.split() key,extra = tuple(parts[0:3]),parts[3:] if key not in finalData or extra: finalData[key] = extra pprint(finalData) 

    Ausgänge:

     {('BOB', '123', '1DB'): ['EXTRA', 'BITS'], ('DAVE', '789', '1DB'): [], ('JIM', '456', '3DB'): ['AX']} 

    Du musst eine Funktion definieren, um deine Zeile in wichtige Bits und Extrabits zu teilen, dann kannst du:

     def split_extra(s): """Return a pair, the important bits and the extra bits.""" return blah blah blah data = {} for line in open('file'): impt, extra = split_extra(line) existing = data.setdefault(impt, extra) if len(extra) > len(existing): data[impt] = extra out = open('newfile', 'w') for impt, extra in data.iteritems(): out.write(impt + extra) 

    Da Sie die Extrabits brauchen, ist der schnellste Weg, um eine Reihe von eindeutigen Einträgen zu erstellen (sort -u wird tun) und dann müssen Sie jeden Eintrag gegeneinander vergleichen, zB

     if x.startswith(y) and not y.startswith(x) 

    Und lassen Sie einfach x und verwerfen y.

    Wenn du perl hast und nur den letzten Eintrag behalten willst:

     cat file.txt | perl -ne 'BEGIN{%k={}} @_ = split(/ /);$kw = shift(@_); $kws{$kw} = "@_"; END{ foreach(sort keys %kws){ print "$_ $kws{$_}";} }' > file.new.txt 

    Die Funktion find_unique_lines funktioniert für ein find_unique_lines oder eine Liste von Strings.

     import itertools def split_line(s): parts = s.strip().split(' ') return " ".join(parts[:3]), parts[3:], s def find_unique_lines(f): result = {} for key, data, line in itertools.imap(split_line, f): if data or key not in result: result[key] = line return result.itervalues() test = """BOB 123 1DB JIM 456 3DB AX DAVE 789 1DB BOB 123 1DB JIM 456 3DB AX DAVE 789 1DB BOB 123 1DB EXTRA BITS""".split('\n') for line in find_unique_lines(test): print line 
      BOB 123 1DB EXTRA BITS
     JIM 456 3DB AX
     DAVE 789 1DB 
    Python ist die beste Programmiersprache der Welt.