Führen Sie Dateien mithilfe einer gemeinsamen Spalte zusammen


8

Ich habe zwei Dateien, aus denen ich eine dritte erstellen möchte, die alle Informationen enthält.

Datei 1:

a 111 
b 222 
c 333 
d 666 
e 777 

Datei 2:

111 x1  
222 x2
333 x3
444 x4 
555 x5 
666 x6 
777 x7 
888 x8

Ich möchte sie wie folgt kombinieren:

111  x1  a
222  x2  b
333  x3  c
444  x4  0
555  x5  0
666  x6  d
777  x7  e
888  x8  0

Hinweis:

Die zweite Spalte von Datei 1 ist eine Teilmenge der ersten Spalte von Datei 2

Antworten:


7

Der joinBefehl macht fast das, was Sie brauchen, wenn die Dateien wie in Ihren Beispielen sortiert sind:

join -12 -a2 file1 file2 -o2.1,2.2,1.1

Sie müssen nur die Nullen zu den Zeilen ohne Übereinstimmung hinzufügen. Sie können den -eSchalter dafür verwenden:

join -12 -a2 file1 file2  -o2.1,2.2,1.1 -e0

Wenn Sie das hinzufügen, -e0brauchen Sie kein Perl :)
— LilloX

@LilloX: Stimmt, danke. Ich habe es versucht, bin aber gescheitert (Tippfehler).
— Choroba

13

Verwenden von join:

join -1 1 -2 2 -a1 -e0 -o'0,1.2,2.1' file2 file1

Der Befehl join verbindet die Zeilen zweier Dateien, die ein gemeinsames Datenfeld verwenden. In diesem Fall: Verbinden Sie die Datei2 und die Datei1 mit dem Feld 1 ( -1 1) der Datei2 und dem Feld 2 ( -2 2) der Datei1.

Die Ausgabe lautet: "Verbundenes Feld, Feld 2 von Datei2, Feld 1 von Datei1" ( -o'0,1.2,2.1'), wenn ein Feld fehlt, setzen Sie 0 ( -e0)

Wenn eine der beiden Dateien mehr Datensätze enthält, fügen Sie diese hinzu (in diesem Fall file2) ( -a1)

Bitte beziehen Sie sich auf die Manpage des Befehls join


Gut. Könnten Sie eine Erklärung hinzufügen?
— Lety

Sicher, aktualisiert :)
— LilloX

5

Ein bisschen awkMagie:

awk 'FNR==NR{a[$2]=$1;next}{if(a[$1]==""){a[$1]=0}; \
    printf "%s%s%s%s%s\n",$1,FS,$2,FS,a[$1]}' \
    file1 file2

oder

awk 'FNR==NR{a[$2]=$1;next}{if(a[$1]==""){a[$1]=0};
    print $1,$2,a[$1]}' file1 file2

Ausgabe

111 x1 a
222 x2 b
333 x3 c
444 x4 0
555 x5 0
666 x6 d
777 x7 e
888 x8 0

Erläuterung

  • FNR==NR{a[$2]=$1;next}

    Läuft über file1( FNR==NR) und erstellt eine Schlüsselwertstruktur. Der Schlüssel ist die zweite Spalte ( $2) von file1, der Wert ist die erste Spalte ( $1) vonfile1

  • {if(a[$1]==""){a[$1]=0};print $1,$2,a[$1]}

    Läuft über file2und

    • if(a[$1]==""){a[$1]=0}

      Wenn der Schlüssel in der ersten Spalte ( $1) in file2nicht vorhanden ist file1, benötigen wir a0

    • print $1,$2,a[$1]

      Drucken (unter Verwendung print) der ersten und zweiten Spalte von file2und des Werts der Schlüsselwertstruktur mit dem Schlüssel der ersten Spalte ( $1) vonfile2

      oder

    • printf "%s%s%s%s%s\n",$1,FS,$2,FS,a[$1]}'

      Drucken (unter Verwendung printf) der ersten und zweiten Spalte von file2und des Werts der Schlüsselwertstruktur mit dem Schlüssel der ersten Spalte ( $1) von file2.

      • FS ist das Trennzeichen zwischen den Spalten aus der Eingabedatei

      • "%s%s%s%s%s\n"

        ist die Formatierung für die Ausgabe

        • %s - String

        • \n - Neue Zeile


Könnten Sie den Code erklären?
— Gforce89

Sicher, Antwort aktualisiert.
— AB

1

Verwenden von q :

$ q "select f2.c1, f2.c2, ifnull(f1.c1,0) from file_2.txt f2 LEFT JOIN file_1.txt f1 on f1.c2 = f2.c1 "
111 x1 a
222 x2 b
333 x3 c
444 x4 0
555 x5 0
666 x6 d
777 x7 e
888 x8 0

Auf diese Weise kann es manchmal besser lesbar sein.


1
Für alle, die sich fragen, qist im Paket python3-q-text-as-data(Python 3) und im Paket python-q-text-as-data(Python 2).
— Kos

Danke, aber wo kann ich dieses qPaket bekommen? Ich scheine nicht in der Lage sein , zu installieren entweder python-q-text-as-dataoder python3-q-text-as-data. "E: Paket python3-q-text-as-data konnte nicht gefunden werden". Mein System bereits installiert python, python2.7, python3, und python3.4.
— Paddy Landau

Möglicherweise ist das Paket zu neu und in Ihrer Distributionsversion nicht verfügbar. Sie können es klonen Github: github.com/harelba/q
— Vi.
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.