
Ich habe eine Datei1 mit 3 Spalten und eine Datei2 mit 4 Spalten auf einem Linux-System. Wie verbinde ich die beiden Dateien basierend auf der Zeichenfolge in Spalte 3 von Datei1 mit der Zeichenfolge in Spalte 2 von Datei2? Datei2 ist eine große Datenbank mit vielen Einträgen. Die Spalten 3 und 2 von Datei1 und Datei2 haben jeweils nur wenige Zeichenfolgen gemeinsam. Ich möchte Datei1 mit verbundenen Zeilen von Datei2 ausgeben, falls die Zeichenfolgen übereinstimmen, und einen Bindestrich für Einträge ohne Übereinstimmungen ausgeben.
Datei1:
300 100 a101
450 410 a400
670 710 a20
700 610 a340
Datei2:
b30 a340 tttttttt 456
b500 a200 llllllll 567
b60 a101 uuuuuuuu 344
b40 a50 kkkkkkkk 223
Ausgabe:
300 100 a101 b60 a101 uuuuuuuu 344
450 410 a400 -
670 710 a20 -
700 610 a340 b30 a340 tttttttt 456
Antwort1
Verwenden von GNU awk
und GNU join
, die unter Linux Standard sind (funktioniert möglicherweise mit Nicht-GNU-Versionen, muss aber nicht):
$ join -a1 -1 3 -2 2 <(sort -k3,3 file1) <(sort -k2,2 file2) |
awk '$4 == "" { $4 = "-" }; {t=$1; $1=$2; $2=$3; $3=t; print}' |
sort
300 100 a101 b60 uuuuuuuu 344
450 410 a400 -
670 710 a20 -
700 610 a340 b30 tttttttt 456
Der join
Befehl verknüpft file1 und file2 in den Feldern 3 und 2. Er verwendetProzesssubstitutionum sicherzustellen, dass beide Dateien nach ihren jeweiligen Schlüsselfeldern sortiert werden. Die -a 1
Option wird verwendet, damit alle Zeilen aus file1
gedruckt werden, auch wenn sie nicht mit einer Zeile aus übereinstimmen file2
.
Leider join
platziert es das Schlüsselfeld von file1 am Anfang jedes Datensatzes. Dies wird behoben, indem awk
die Felder wieder in ihre ursprüngliche Reihenfolge verschoben werden, wobei eine Variable namens t
als temporärer Platzhalter für den Wert von $1 verwendet wird. Das awk-Skript fügt außerdem das abschließende Bindestrichzeichen in Feld $4 hinzu, wenn es keine Übereinstimmung zwischen den Dateien gab (weil es join
dies selbst nicht tut).
Abschließend wird die Ausgabe sortiert.