Hoe anti-join of inverse join in bash te doen

Ik wil uitvoeren wat sommige data-analysesoftware een anti-join noemt: verwijder die regels uit een lijst overeenkomende regels in een andere lijst. Hier zijn wat speelgoedgegevens en de verwachte uitvoer:

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

Reacties

Antwoord

Ik zou join niet gebruiken hiervoor omdat voor join invoer moet worden gesorteerd, wat een onnodige complicatie is voor zon eenvoudige taak. U kunt in plaats daarvan grep gebruiken:

$ grep -vxFf list2 list1 a b 

Of awk:

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

Als de bestanden al zijn gesorteerd, is een alternatief voor join -v 1 comm -23

$ comm -23 list1 list2 a b 

Opmerkingen

  • sort vermijden met grep is geweldig voor de speelgoedgegevens die ik heb verstrekt. Bedankt! In de echte wereld heeft mijn bestand1 vaak meerdere kolommen met gegevens, waarvan er één wordt gebruikt voor de join. Een aangepaste versie van uw awk code zou deze use case aanpakken.
  • @Josh ja, verander gewoon de $0 met $N waar N is het veldnummer waaraan u deelneemt.
  • Dit werkt zelfs als de kolomnummers in file1 en file2 verschillend zijn: zoals awk ' NR == FNR {++ a [$ 2]}! a [$ 5] ' list2 list1; vrij gebruikelijk dat het tagbestand een ander formaat heeft dan de hoofdgegevens.

Answer

Een manier om doe dit met het join hulpprogramma is:

$ join -v 1 list1 list2 a b 

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *