2017-09-08 5 views
1

J'ai deux fichiers texte dont j'ai besoin de comparer le contenu car l'un d'entre eux manque 2 éléments que l'autre a, mais je ne suis pas sûr car ils sont longs. J'ai essayé diff et vimdiff sans chance. Mes fichiers sont tous deux formatés comme celui-ci dans un ordre dispersé:Comparaison du contenu des fichiers texte en ignorant l'ordre et le format

item1 item2 item3 
item8 item10 item6 
item32 item12 item7 

Comment puis-je choisir quels éléments l'un des fichiers texte a, mais l'autre manque, tout en ignorant le format et l'ordre?

+0

vous avez écrit ** deux fichiers texte **, poster les fichiers d'entrée et les attendus résultat – RomanPerekhrest

Répondre

0

exemple Cyrus est de loin plus court et plus au point, mais pensé que je pratique un peu (bavard) awk ing ...

données Exemple:

$ cat file1 
     item2 item3 
item8 item10 item6 
item32 item12 item7 

$ cat file2 
item1 item2 item3 
item8    item6 
     item12 item7 

Hypothèses:

  • alors que la description dit quelques éléments pourraient me manquer dans un fichier, je vais supposer qu'il pourrait y avoir des éléments manquants dans les deux fichiers
  • ne va pas à vous soucier de tri (pour l'entrée ou de sortie)
  • sans indications sur la façon dont pour afficher la sortie, je vais juste faire mon thang, pour inclure l'affichage du nom du fichier que l'élément est absent de

Une solution possible awk:

$ cat text.awk 
BEGIN { RS="" } 

NR==FNR { afile=FILENAME ; for (i=1;i<=NF;i++) a[$i]=1 ; next } 
     { bfile=FILENAME ; for (i=1;i<=NF;i++) b[$i]=1  } 

END { 
    for (x in a) 
     { if (! b[x]) 
      { printf "missing from %s : %s\n",bfile,x } 
     } 
    for (x in b) 
     { if (! a[x]) 
      { printf "missing from %s : %s\n",afile,x } 
     } 
} 
  • RS="": séparateur de ligne réglée (RS) à la chaîne vide; ce transforme un fichier dans un enregistrement à long
  • NR==NFR: si tel est le premier (de deux) fichiers ...
  • afile=FILENAME: enregistrer le nom de fichier pour une impression ultérieure
  • for/a[$i]=1: utiliser des champs d'entrée 1-NF comme index pour tableau associatif a, la mise en valeur du tableau 1 (alias « true »)
  • next: lire l'enregistrement suivant, ce qui signifie dans ce cas lire le fichier suivant
  • NR!=FNR: si tel est le deuxième (de deux) fichiers ...
  • s ame traitement sauf peupler bfile et tableau associatif b
  • END ...: traiter nos tableaux ...
  • for (x in a): boucle à travers les indices de tableau a et assigner à une variable x, et s'il n'y a pas d'entrée indexée comparable dans le tableau b (! b[x]) puis imprimer un message sur l'index de tableau (le nom fait de l'élément du fichier original) manquant de bfile
  • for (x in b): même que la boucle précédente, sauf la vérification des éléments de bfile mais pas dans afile

Ce script awk en action:

$ awk -f text.awk file1 file2 
missing from file2 : item10 
missing from file2 : item32 
missing from file1 : item1 

# switch the order of the input files => same messages, just different order 
$ awk -f text.awk file2 file1 
missing from file1 : item1 
missing from file2 : item10 
missing from file2 : item32 
0

Je crois que vous pouvez utiliser la commande comm .. mais vous devriez avoir les deux fichiers dans l'ordre de tri pour comparer:

comm -23 f1 f2 # will give whatever lines not matching in file1 against file2 
comm -12 f1 f2 # will give matching lines 
comm -13 f1 f2 # will give whatever lines not matching in file2 against file 1 
+1

merci Mr.batMan. :) Je l'ai corrigé. – VIRA

0

Utilisez comm pour comparer votre dossier afin de trouver ce qui est commun ou distinct dans les .

$ cat file1 
item1 item2 item3 
item8 item10 item6 
item32 item12 item5 

$ cat file2 
item1 item2 item3 
item8 item15 item6 
item32 item12 item7 

comm -23 file1 file2 renvoie les lignes qui sont en fichier1 mais pas dans fichier2
comm -13 file1 file2 renvoie les lignes qui sont en fichier2 mais pas dans fichier1
comm -12 file1 file2 renvoie lignes communes dans les deux fichiers

comm nécessite des fichiers d'entrée à être trié. Nous allons d'abord convertir spaces en \n via sed, puis trier via tri.

$ comm -23 <(sed 's/ \+/\n/g' file1 | sort) <(sed 's/ \+/\n/g' file2 | sort) 
item10 
item5 

$ comm -13 <(sed 's/ \+/\n/g' file1 | sort) <(sed 's/ \+/\n/g' file2 | sort) 
item15 
item7 

$ comm -12 <(sed 's/ \+/\n/g' file1 | sort) <(sed 's/ \+/\n/g' file2 | sort) 
item1 
item12 
item2 
item3 
item32 
item6 
item8 

- Ma réponse se termine ici. ---

Mais pour plus d'informations, page man de comm dit:

With no options, comm produce three-column output. Column one contains lines unique to FILE1, column two contains lines unique to FILE2, and column three contains lines common to both files. 

    -1  suppress column 1 (lines unique to FILE1) 

    -2  suppress column 2 (lines unique to FILE2) 

    -3  suppress column 3 (lines that appear in both files) 

Par conséquent:

$ comm <(sed 's/ \+/\n/g' file1 | sort) <(sed 's/ \+/\n/g' file2 | sort) 
       item1 
item10 
       item12 
     item15 
       item2 
       item3 
       item32 
item5 
       item6 
     item7 
       item8