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
- Relatie met unix.stackexchange.com/q/11343/117549
- Beantwoordt dit uw vraag? Is er een tool om de regels in het ene bestand te krijgen die niet in het andere staan?
- @Muru, ja, dat bericht biedt de oplossingen gepresenteerd in het antwoord van Terdon '. Toen ik echter zocht naar " bash anti-join " (de terminologie die ik associeer met dit soort processen), deed ik dat niet ' niets nuttigs vinden. Mijn OP (die anderen hebben bewerkt) verklaarde dat mijn expliciete doel bij het stellen van deze vraag was om de term " anti-join " te associëren met de oplossingen, zodat het zoeken op deze term deze oplossingen oplevert. Bedankt.
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 metgrep
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 uwawk
code zou deze use case aanpakken. - @Josh ja, verander gewoon de
$0
met$N
waarN
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