2010-12-08 19 views
2

J'ai deux fichiersComment supprimer des lignes dupliquées sur un fichier basé sur un champ commun entre deux fichiers avec AWK?

  1. fichier 1 contient 3 champs

  2. fichier 2 contient 4 champs

Le nombre de lignes de fichier 1 est beaucoup plus petite que celle du fichier 2

Je voudrais comparer entre deux fichiers basés sur le 1er champ avec l'opération suivante

Si le premier champ dans une ligne de fichier 1 apparaît dans le premier champ d'une ligne dans le fichier 2, ne pas imprimer cette ligne pour le fichier 2.

Tout conseil serait reconnaissant.

Input File 1 

S13109 3739 31082 
S45002 3800 31873 
S43722 3313 26638 

Input File 2 

S13109 3738 31081 0 
S13109 3737 31080 0 
S00033 3008 29985 0 
S00033 3007 29984 0 
S00022 4130 31838 0 
S00022 4129 31837 0 
S00188 3317 27372 0 
S45002 3759 31832 0 
S45002 3758 31831 0 
S45002 3757 31830 0 
S43722 3020 26345 0 
S43722 3019 26344 0 
S00371 3737 33636 0 
S00371 3736 33635 0 

Desired Output 

S00033 3008 29985 0 
S00033 3007 29984 0 
S00022 4130 31838 0 
S00022 4129 31837 0 
S00188 3317 27372 0 
S00371 3737 33636 0 
S00371 3736 33635 0 

Répondre

6

awk 'FNR==NR{a[$1]++;next}!a[$1]' file1 file2

Comment ça marche:

FNR==NR 

Lorsque vous avez deux (ou plus) les fichiers d'entrée à awk, NR sera réinitialisé à 1 sur la première ligne du fichier suivant tandis que FNR continuera d'augmenter à partir de l'endroit où il s'est arrêté. En vérifiant FNR==NR, nous vérifions essentiellement si nous analysons actuellement le premier fichier.

a[$1]++ 

Si nous sont l'analyse du premier fichier (voir ci-dessus), puis créer un tableau associatif avec le premier champ $1 comme l'incrément de touche et après la valeur de 1. Cela nous permet essentiellement de créer un « vu » liste.

next 

Cette commande indique à awk de ne pas traiter d'autres commandes et de lire l'enregistrement suivant et de recommencer. Nous faisons cela parce que fichier1 est uniquement destinée à définir le tableau associatif

!a[$1] 

Cette ligne exécute uniquement lorsque FNR==NR est faux, à savoir que nous sommes pas l'analyse syntaxique fichier1 et doit donc être l'analyse syntaxique fichier2. Nous utilisons ensuite le premier champ $1 de fichier2 comme clé pour indexer dans notre liste 'vu' créée plus tôt. Si la valeur renvoyée est 0, cela signifie que nous ne l'avons pas vu dans le fichier 1 et que nous devrions donc imprimer cette ligne. Inversement, si la valeur est non nulle, alors l'a fait le voir dans le fichier 1 et ainsi nous devrions pas imprimer sa valeur. Notez que !a[$1] est équivalent à !a[$1]{print} parce que l'action par défaut quand il n'est pas donné est d'imprimer la ligne entière.

+0

Juste testé le script. ça fonctionne très bien. À votre santé. – Tony

+0

Cher SiegeX. Votre explication est très instructive pour un débutant comme moi. Le problème que j'ai avec l'écriture de ce type de script est qu'il existe de nombreuses approches pour faire la même tâche, mais la meilleure est difficile à réaliser. Je suppose que cela vient avec l'expérience. Merci beaucoup pour votre aide. – Tony

+0

FNR se réinitialise pour chaque fichier. NR continue d'augmenter. –

1

Si vous n'avez pas besoin de préserver l'ordre des lignes, vous pouvez utiliser la substitution de processus dans Bash, shell Korn ou Z ainsi que les services publics et joinsort:

join -v 2 <(sort file_1) <(sort file_2) 

Si vous êtes En utilisant un shell sans substitution de processus, vous devrez pré-trier les fichiers.