Quero realizar o que alguns softwares de análise de dados chamam de anti-join: remover de uma lista essas linhas linhas correspondentes em outra lista. Aqui estão alguns dados de brinquedo e a saída esperada:
$ echo -e "a\nb\nc\nd" > list1 $ echo -e "c\nd\ne\nf" > list2 $ antijoincommand list1 list2 a b
Comentários
- Relacionando unix.stackexchange.com/q/11343/117549
- Isso responde à sua pergunta? Existe uma ferramenta para obter as linhas de um arquivo que não estão em outro?
- @Muru, sim, essa postagem fornece as soluções apresentado na resposta de Terdon '. No entanto, quando estava pesquisando por " bash anti-join " (a terminologia que associo a esse tipo de processo), não ' t encontrar algo útil. Meu OP (que outros editaram) afirmou que meu propósito explícito ao fazer esta pergunta era associar o termo " anti-join " com as soluções, de modo que pesquisar esse termo produz essas soluções. Obrigado.
Resposta
Eu não usaria join
para isso porque join
exige que a entrada seja classificada, o que é uma complicação desnecessária para um trabalho tão simples. Você pode usar grep
:
$ grep -vxFf list2 list1 a b
Ou awk
:
$ awk "NR==FNR{++a[$0]} !a[$0]" list2 list1 a b
Se os arquivos já estiverem classificados, uma alternativa para join -v 1
seria comm -23
$ comm -23 list1 list2 a b
Comentários
- Evitar
sort
comgrep
é ótimo pelos dados de brinquedo que forneci. Obrigado! No mundo real, meu arquivo1 geralmente tem várias colunas de dados, uma das quais está sendo usada para a junção. Uma versão modificada de seuawk
o código resolveria esse caso de uso. - @Josh sim, basta alterar o
$0
com$N
ondeN
é o número do campo no qual você está se juntando. - Isso funciona mesmo se os números das colunas em arquivo1 e arquivo2 forem diferentes: como awk ' NR == FNR {++ a [$ 2]}! a [$ 5] ' lista2 lista1; bastante comum para o arquivo de tag ter um formato diferente dos dados principais.
Resposta
Uma maneira de faça isso com o utilitário join
:
$ join -v 1 list1 list2 a b