Entfernt die gesamte Zeile in einer Datei, wenn die erste Spalte wiederholt wird

Entfernt die gesamte Zeile in einer Datei, wenn die erste Spalte wiederholt wird

Ich habe eine Datei mit zwei Spalten und 10 Millionen Zeilen. Die erste Spalte enthält viele sich wiederholende Werte, aber in Spalte 2 gibt es einen eindeutigen Wert. Ich möchte die sich wiederholenden Zeilen entfernen und nur eine behalten, indem ich awk. Hinweis: Die Datei ist nach Werten in Spalte 1 sortiert. Beispiel:

1.123 -4.0
2.234 -3.5
2.234 -3.1
2.234 -2.0
4.432 0.0
5.123 +0.2
8.654 +0.5
8.654 +0.8
8.654 +0.9
.
.
.
.

Erwartete Ausgabe

1.123 -4.0
2.234 -3.5
4.432 0.0
5.123 +0.2
8.654 +0.5
.
.
.
.

Antwort1

Einige Möglichkeiten:

  1. awk

    awk '!a[$1]++' file
    

    Dies ist eine sehr komprimierte Art, dies zu schreiben:

    awk '{if(! a[$1]){print; a[$1]++}}' file
    

    Wenn also das aktuelle erste Feld ( $1) nicht im aArray ist, drucken Sie die Zeile und fügen Sie das 1. Feld hinzu a. Wenn wir dieses Feld das nächste Mal sehen, wird es im Array sein und daher nicht gedruckt.

  2. Perl

    perl -ane '$k{$F[0]}++ or print' file
    

    oder

    perl -ane 'print if !$k{$F[0]}++' file
    

    Dies ist im Grunde dasselbe wie das awkeine. Das -nveranlasst Perl, die Eingabedatei Zeile für Zeile zu lesen und das von bereitgestellte Skript -eauf jede Zeile anzuwenden. Das -ateilt jede Zeile automatisch bei Leerzeichen auf und speichert die resultierenden Felder im @FArray. Schließlich wird das erste Feld zum %kHash hinzugefügt und wenn es nicht bereits vorhanden ist, wird die Zeile gedruckt. Das Gleiche könnte man auch so schreiben:

    perl -e 'while(<>){
                @F=split(/\s+/); 
                print unless defined($k{$F[0]}); 
                $k{$F[0]}++;
             }' file
    
  3. Kerndienstprogramme

    rev file | uniq -f 1 | rev
    

    Diese Methode funktioniert, indem zuerst die Zeilen in umgekehrt werden, fileso dass eine Zeile mit 12 345 nun 543 21 ist. Dann uniq -f 1ignorieren wir das erste Feld, also die Spalte mit 543. Innerhalb befinden sich Felder file. Die Verwendung uniqvon hier hat den Effekt, dass alle doppelten Zeilen herausgefiltert werden und nur jeweils 1 behalten wird. Zuletzt bringen wir die Zeilen mit einer weiteren Umkehrung wieder in ihre ursprüngliche Reihenfolge.

  4. GNU sort (alsempfohlenvon @StéphaneChazelas)

    sort -buk1,1
    

    Das -bFlag ignoriert führende Leerzeichen und -ubedeutet, dass nur eindeutige Felder gedruckt werden. Der clevere Teil ist das -k1,1. Das -kFlag legt das Feld fest, nach dem sortiert werden soll. Es nimmt das allgemeine Format an, -k POS1[,POS2]was bedeutet, dass beim Sortieren nur die Felder bis POS2 berücksichtigt werden POS1. Also -k1,1bedeutet, dass nur das 1. Feld berücksichtigt wird. Abhängig von Ihren Daten möchten Sie möglicherweise auch eine dieser Optionen hinzufügen:

     -g, --general-numeric-sort
          compare according to general numerical value
     -n, --numeric-sort
          compare according to string numerical value
    

Antwort2

Wenn die erste Spalte immer 5 Zeichen lang ist, können Sie einfach Folgendes verwenden uniq:

uniq -w 5 file

Wenn nicht, verwenden Sie awk:

awk '$1!=a{print $0; a=$1}' file

Bei einer großen Datei wäre die erste Methode auf jeden Fall schneller.

verwandte Informationen