Chcę wykonać to, co niektóre programy do analizy danych nazywają anty-złączeniem: usuń z jednej listy te linie pasujące wiersze na innej liście. Oto niektóre dane dotyczące zabawki i oczekiwane wyniki:
$ echo -e "a\nb\nc\nd" > list1 $ echo -e "c\nd\ne\nf" > list2 $ antijoincommand list1 list2 a b
Komentarze
- Powiązane unix.stackexchange.com/q/11343/117549
- Czy to odpowiada na Twoje pytanie? Czy jest narzędzie do pobierania wierszy w jednym pliku, których nie ma w innym?
- @Muru, tak, ten post zawiera rozwiązania przedstawione w odpowiedzi Terdona '. Jednak gdy szukałem " bash anti-join " (terminologia, którą kojarzę z tego rodzaju procesami), nie ' nie znajduję niczego przydatnego. Mój OP (który edytowali inni) stwierdził, że moim wyraźnym celem zadając to pytanie było powiązanie terminu " anti-join " z rozwiązania, tak że wyszukiwanie tego terminu daje te rozwiązania. Dzięki.
Odpowiedź
Nie użyłbym join
dlatego, że join
wymaga posortowania danych wejściowych, co jest niepotrzebną komplikacją w przypadku tak prostej pracy. Zamiast tego można użyć grep
:
$ grep -vxFf list2 list1 a b
Lub awk
:
$ awk "NR==FNR{++a[$0]} !a[$0]" list2 list1 a b
Jeśli pliki są już posortowane, alternatywą dla join -v 1
byłoby comm -23
$ comm -23 list1 list2 a b
Komentarze
- Unikanie
sort
zgrep
jest świetne za dostarczone przeze mnie dane zabawki. Dzięki! W prawdziwym świecie mój plik1 często zawiera wiele kolumn danych, z których jedna jest używana do łączenia. Zmodyfikowana wersja Twojegoawk
kod rozwiązałby ten przypadek użycia. - @Josh tak, po prostu zmień
$0
na$N
gdzieN
to numer pola, do którego się przyłączasz. - Działa to nawet wtedy, gdy numery kolumn w pliku1 i pliku2 są różne, np. awk ' NR == FNR {++ a [$ 2]}! a [$ 5] ' list2 list1; dość typowe dla pliku znaczników jest inny format niż główne dane.
Odpowiedź
Jeden sposób zrób to za pomocą narzędzia join
:
$ join -v 1 list1 list2 a b