Jak to udělat anti-join nebo inverzní join v bash

Chci provést to, co některý software pro analýzu dat nazývá anti-join: odstranit tyto řádky z jednoho seznamu odpovídající řádky v jiném seznamu. Tady je několik údajů o hračkách a očekávaný výstup:

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

Komentáře

Odpověď

Nepoužívám join z tohoto důvodu, protože join vyžaduje třídění vstupu, což je pro tak jednoduchou práci zbytečná komplikace. Místo toho můžete použít grep:

$ grep -vxFf list2 list1 a b 

Nebo awk:

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

Pokud jsou soubory již seřazeny, alternativou k join -v 1 by byla comm -23

$ comm -23 list1 list2 a b 

Komentáře

  • Vyhýbání se sort s grep je skvělé za údaje o hračce, které jsem poskytl. Díky! Ve skutečném světě má můj soubor1 často více sloupců dat, z nichž jeden se používá pro spojení. Upravená verze vašeho awk kód by řešil tento případ použití.
  • @Josh ano, stačí změnit $0 na $N kde N je číslo pole, ke kterému se připojujete.
  • Funguje to i v případě, že se čísla sloupců v souborech1 a souborech 2 liší: jako awk ' NR == FNR {++ a [$ 2]}! a [$ 5] ' list2 list1; celkem obvyklé, že soubor tagu má jiný formát než hlavní data.

Odpověď

Jeden způsob, jak proveďte to pomocí join nástroje:

$ join -v 1 list1 list2 a b 

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *