Comment faire une anti-jointure ou une jointure inverse dans bash

Je souhaite effectuer ce que certains logiciels danalyse de données appellent une anti-jointure: supprimer dune liste ces lignes lignes correspondantes dans une autre liste. Voici quelques données sur les jouets et le résultat attendu:

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

Commentaires

Réponse

Je nutiliserais pas join pour cela, car join nécessite le tri des entrées, ce qui est une complication inutile pour un travail aussi simple. Vous pouvez à la place utiliser grep:

$ grep -vxFf list2 list1 a b 

Ou awk:

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

Si les fichiers sont déjà triés, une alternative à join -v 1 serait comm -23

$ comm -23 list1 list2 a b 

Commentaires

  • Éviter sort avec grep est génial pour les données de jouet que jai fournies. Merci! Dans le monde réel, mon fichier1 contient souvent plusieurs colonnes de données, dont lune est utilisée pour la jointure. Une version modifiée de votre awk le code répondrait à ce cas dutilisation.
  • @Josh oui, il suffit de changer $0 par $NN est le numéro de champ sur lequel vous rejoignez.
  • Cela fonctionne même si les numéros de colonne dans file1 et file2 sont différents: comme awk ' NR == FNR {++ a [$ 2]}! a [$ 5] ' list2 list1; tout à fait habituel que le fichier de balise ait un format différent des données principales.

Réponse

Une façon de faites ceci avec lutilitaire join est:

$ join -v 1 list1 list2 a b 

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *