GNU/Linux >> Tutoriels Linux >  >> Linux

Comparez deux colonnes de fichiers différents et imprimez si cela correspond ?

J'utilise Solaris 10 et donc les options grep impliquant -f ne fonctionnent pas.

J'ai deux fichiers séparés par des tubes :

fichier1 :

abc|123|BNY|apple|
cab|234|cyx|orange|
def|kumar|pki|bird|

fichier 2 :

abc|123|
kumar|pki|
cab|234

Je voudrais comparer les deux premières colonnes de file2 avec file1 (recherche dans tout le contenu de file1 dans les deux premières colonnes) si elles correspondent à la ligne correspondante de file1. Recherchez ensuite la deuxième ligne du fichier 2 et ainsi de suite.

Sortie attendue :

abc|123|BNY|apple|
cab|234|cyx|orange|

Les fichiers que j'ai sont énormes, contenant environ 400 000 lignes, donc je voudrais rendre l'exécution rapide.

Réponse acceptée :

C'est pour cela qu'awk a été conçu :

$ awk -F'|' 'NR==FNR{c[$1$2]++;next};c[$1$2] > 0' file2 file1
abc|123|BNY|apple|
cab|234|cyx|orange|

Explication

  • -F'|' :définit le séparateur de champs sur | .
  • NR==FNR :NR est le numéro de ligne d'entrée courant et FNR le numéro de ligne du fichier courant. Les deux ne seront égaux que pendant la lecture du 1er fichier.
  • c[$1$2]++; next :s'il s'agit du 1er fichier, enregistrez les deux premiers champs dans le c déployer. Ensuite, passez à la ligne suivante pour que cela ne soit appliqué que sur le 1er fichier.

  • c[$1$2]>0 :le bloc else ne sera exécuté que si c'est le deuxième fichier donc on vérifie si les champs 1 et 2 de ce fichier ont déjà été vus (c[$1$2]>0 ) et s'ils l'ont été, nous imprimons la ligne. Dans awk , l'action par défaut est d'imprimer la ligne donc si c[$1$2]>0 est vrai, la ligne sera imprimée.

Alternativement, puisque vous avez tagué avec Perl :

perl -e 'open(A, "file2"); while(<A>){/.+?|[^|]+/ && $k{$&}++};
         while(<>){/.+?|[^|]+/ && do{print if defined($k{$&})}}' file1

Explication

La première ligne ouvrira file2 , tout lire jusqu'au 2ème | (.+?|[^|]+ ) et enregistrez-le (le $& est le résultat du dernier opérateur de correspondance) dans le %k hachage.

La deuxième ligne traite file1, utilise la même regex pour extraire les deux premières colonnes et imprimer la ligne si ces colonnes sont définies dans le %k hachage.

Les deux approches ci-dessus devront contenir les 2 premières colonnes de file2 en mémoire. Cela ne devrait pas poser de problème si vous n'avez que quelques centaines de milliers de lignes, mais si c'est le cas, vous pouvez faire quelque chose comme

cut -d'|' -f 1,2 file2 | while read pat; do grep "^$pat" file1; done

Mais ce sera plus lent.

Connexe :Copiez tous les programmes et fichiers installés sur un disque dur (avec Windows 7 32 bits) et clonez-le/transférez-le sur un autre ordinateur avec Windows 7 64 bits ?
Linux
  1. Comment comparer trois fichiers sous Linux à l'aide de l'outil diff3

  2. Rechercher des fichiers texte contenant deux mots différents (n'importe quel ordre, n'importe quelle ligne) ?

  3. Lum - Fusionner des colonnes à partir de deux fichiers distincts ?

  4. Comment comparer le contenu de deux archives tar

  5. comment fusionner deux fichiers de manière cohérente ligne par ligne

Comment supprimer des fichiers et des répertoires à l'aide de la ligne de commande Linux

Comment comparer et fusionner des fichiers texte sous Linux

Comment comparer et fusionner des fichiers texte sous Linux (partie 2)

Comment comparer deux fichiers dans un terminal Linux

Comparez deux fichiers sous Linux - Utilisation de diff, vimdiff et colordiff

Différence d'espace entre deux fichiers sous Linux