Befehl, der den Wert nur einmal druckt, obwohl er oft angezeigt wird

8

Ich habe eine große Textdatei, in der sich die Werte oft wiederholen. Gibt es einen Befehl, den ich verwenden kann, der die Datei durchläuft, und wenn ein Wert einmal erscheint, wiederholen Sie ihn nicht noch einmal?

SO4
HOH
CL
BME
HOH
SO4
HOH
CL
BME
HOH
SO4
HOH
SO4
HOH
CL
BME
HOH
SO4
HOH
CL
BME
HOH
CL

Es sollte also ungefähr so aussehen:

S04   
HOH  
CL   
BME 

Die Sache ist, dass ich eine große Anzahl verschiedener Werte habe, also kann ich es nicht manuell machen, wie hier.

    
djordje 06.01.2018, 09:26

3 Antworten

11

Sie können den Befehl sort mit der Option --unique :

verwenden
sort -u input-file

Wenn Sie das Ergebnis anstelle der Standardausgabe in FILE schreiben möchten, verwenden Sie die Option --output=FILE :

sort -u input-file -o output-file

Der Befehl uniq kann auch angewendet werden. In diesem Fall müssen die identischen Zeilen konsequent sein, daher muss die Eingabe vorläufig sortiert werden, dank @RonJohn für diese Anmerkung:

sort input-file | uniq > output-file

Ich mag den Befehl sort wegen ähnlicher Fälle aus Gründen der Einfachheit. Wenn Sie jedoch mit großen Arrays arbeiten, verwenden Sie den Ansatz von awk von John1024 Antwort könnte mächtiger sein. Hier ist ein Zeitvergleich zwischen den genannten Ansätzen, der auf eine Datei (basierend auf dem obigen Beispiel) mit fast 5 Millionen Zeilen angewendet wird:

$ cat input-file | wc -l
20000000

$ TIMEFORMAT=%R
$ time sort -u input-file | wc -l
64
7.495

$ time sort input-file | uniq | wc -l
64
7.703

$ time awk '!a[$0]++' input-file | wc -l      # from John1024's answer
64
1.271

$ time datamash rmdup 1 < input-file | wc -l  # from αғsнιη's answer
64
0.770

Ein weiterer wesentlicher Unterschied ist dass von @Ruslan erwähnt wurde:

  

sort -u druckt das Ergebnis nur, wenn die Eingabe beendet ist   Dieser Befehl awk druckt jede neue Ergebniszeile im laufenden Betrieb (dies   kann für Pipe-Input wichtiger sein als Datei).

Hier ist eine Illustration:

Im obigen Beispiel generiert die Schleife (unten gezeigt) 500 Zufallskombinationen mit jeweils drei Zeichen Länge der Buchstaben A-D. Diese Kombinationen werden zu awk oder sort geleitet.

for i in {1..500}; do cat /dev/urandom | tr -dc A-D | head -c 3; echo; done
    
pa4080 06.01.2018, 09:35
15

Wenn Sie die Ausgabezeilen in der gleichen Reihenfolge wie die Eingabezeilen halten möchten, verwenden Sie:

$ awk '!a[$0]++' file
SO4
HOH
CL
BME

Wie es funktioniert:

Hierbei wird das assoziative Array a verwendet, um zu zählen, wie oft jede Zeile zuvor gesehen wurde. Wenn es zuvor noch nicht gesehen wurde, wird die Zeile gedruckt.

    
John1024 06.01.2018 09:36
1

Sie können GNU datamash auch hier verwenden und behält die Zeilenreihenfolge bei.

datamash rmdup 1 < infile
    
devWeek 27.03.2018 20:05

Tags und Links