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.

  • Extrahieren Sie jede Sequenzdaten als einzelne Datei
  • Bash-Skript, um eine einzelne Python-Funktion aus einer Datei auszuwählen
  • Ändern Sie die erste Zeile einer Datei mit bash
  • Julianischen Tag in Datum umwandeln
  • Sortiere ein Feld in aufsteigender Reihenfolge und lösche die erste und letzte Zahl
  • Entfernen von In-Feld-Anführungszeichen in csv-Datei
  • 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.

  • Auswertung von mathematischen Gleichungen aus unsicherer Benutzereingabe in Python
  • Wie kann man einen String mit einem gleichen Symbol auswerten?
  • Eval () gibt zur Laufzeit keine Variable zu
  • Verwendung von eval in Python, MATLAB, etc
  • Warum gibt es eine Längengrenze für python's eval?
  • Wie funktioniert Str (Liste)?
  • 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.