
Angenommen, ich habe zwei Befehle, die einen Text zurückgeben. Zum Beispiel:
$ ./c1
/usr/bin/foo
/usr/bin/bar
/usr/bin/baz
$ ./c2
/usr/bin/foo
/usr/bin/qux
/usr/bin/buzz
/usr/bin/bar
Ich möchte die doppelten Zeilen entfernen. Das heißt, die Ausgabe lautet (die Reihenfolge ist nicht wichtig):
/usr/bin/baz
/usr/bin/qux
/usr/bin/buzz
Wie würde ich dabei vorgehen?
Antwort1
Eine relativ einfache Pipeline sollte den Zweck erfüllen:
(./c1; ./c2) | sort -u
Die Klammern übernehmen die Standardausgabe von beiden ./c1
und ./c2
die Standardeingabe des sort
Befehls. Die Option -u
druckt nur eine Zeile jeder Gruppe übereinstimmender Zeilen.
Danke an John WH Smith für den Hinweis auf eine Vereinfachung und an Bakuriu für seine Einsicht.
Antwort2
Mit comm
von GNU coreutils
:
$ comm -3 <(sort -u <(./c1)) <(sort -u <(./c2)) | tr -d '\t'
/usr/bin/baz
/usr/bin/buzz
/usr/bin/qux
Aus man comm
:
Compare sorted files FILE1 and FILE2 line by line.
With no options, produce three-column output. Column one contains
lines unique to FILE1, column two contains lines unique to FILE2, and
column three contains lines common to both files.
-1 suppress column 1 (lines unique to FILE1)
-2 suppress column 2 (lines unique to FILE2)
-3 suppress column 3 (lines that appear in both files)
Antwort3
awk-pipe, um nur das erste Vorkommen einer Eingabezeile durchzulassen:
( ./c1 ; ./c2 ) | awk '!u[$0]++'
Das Sortieren nimmt keine Zeit in Anspruch, erfordert aber einen Speicher für die angezeigten Zeilen. Für große Eingabemengen ist das also sort
möglicherweise uniq
besser ...
Antwort4
Ich würde empfehlen, sed
den Text zu analysieren und doppelte Zeilen zu entfernen. Der erste Befehl behält also die doppelte Zeile bei
sed '$!N; /^\(.*\)\n\1$/!P; D'
Der zweite Befehl löscht die Duplikate
sed -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P'