So führen Sie Anti-Join- oder Inverse-Joins in bash durch

Ich möchte das ausführen, was eine Datenanalyse-Software als Anti-Join bezeichnet: Entfernen Sie diese Zeilen aus einer Liste übereinstimmende Zeilen in einer anderen Liste. Hier sind einige Spielzeugdaten und die erwartete Ausgabe:

$ echo -e "a\nb\nc\nd" > list1 $ echo -e "c\nd\ne\nf" > list2 $ antijoincommand list1 list2 a b 

Kommentare

finde nichts Nützliches. Mein OP (das andere bearbeitet haben) gab an, dass mein ausdrücklicher Zweck beim Stellen dieser Frage darin bestand, den Begriff " Anti-Join " mit zu verknüpfen die Lösungen, so dass die Suche nach diesem Begriff diese Lösungen ergibt. Danke.

Antwort

Ich würde join nicht verwenden Dies liegt daran, dass join eine Sortierung der Eingabe erfordert, was für einen so einfachen Job eine unnötige Komplikation darstellt. Sie können stattdessen grep:

$ grep -vxFf list2 list1 a b 

Oder awk:

$ awk "NR==FNR{++a[$0]} !a[$0]" list2 list1 a b 

Wenn die Dateien bereits sortiert sind, wäre eine Alternative zu join -v 1 comm -23

$ comm -23 list1 list2 a b 

Kommentare

  • Das Vermeiden von sort mit grep ist großartig Für die Spielzeugdaten, die ich bereitgestellt habe. Danke! In der realen Welt enthält meine Datei1 häufig mehrere Datenspalten, von denen eine für den Join verwendet wird. Eine modifizierte Version Ihres awk Code würde diesen Anwendungsfall ansprechen.
  • @Josh ja, ändern Sie einfach die $0 mit $N wobei N ist die Feldnummer, der Sie beitreten.
  • Dies funktioniert auch dann, wenn die Spaltennummern in Datei1 und Datei2 unterschiedlich sind: wie awk ' NR == FNR {++ a [$ 2]}! a [$ 5] ' list2 list1; Es ist durchaus üblich, dass die Tag-Datei ein anderes Format als die Hauptdaten hat.

Antwort

Ein Weg zu Führen Sie dies mit dem Dienstprogramm join aus:

$ join -v 1 list1 list2 a b 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.