Comment comparer deux fichiers différents ligne par ligne sous Unix?

13

Fichier1:

123
234
345
456

Fichier2:

123
234
343
758

Sortie attendue: File3:

TRUE
TRUE
FALSE
FALSE

le code doit donc comparer deux fichiers et afficher «VRAI» s'il correspond, sinon il doit afficher «FAUX» dans le nouveau fichier. Quelqu'un pourrait-il s'il vous plaît fournir la solution pour cela?

Velu
la source
10
Que se passe-t-il si les deux fichiers sont de longueur inégale? Avec quelle partie de la solution à ce problème rencontrez-vous des problèmes?
Kusalananda
9
Vous voudrez peut-être y jeter un œil diff.
Panki
2
Une autre commande utile dans ces situations est comm. Il facilite la liste des lignes que les deux fichiers ont en commun ou sont uniques à l'un ou à l'autre.
Giacomo Alzetta
1
@GiacomoAlzetta Le problème, commc'est qu'il nécessite une entrée triée. Mis à part le fait que l'exemple de la question a une entrée triée, la question n'affirme jamais que ce sont les données réelles qui sont utilisées et ne dit jamais rien sur l'ordre des données.
Kusalananda
2
L' nlastuce de αғsнιη est utile commpour imposer un tri sur les fichiers.
glenn jackman

Réponses:

56

Utilisez la diffcommande comme suit, dans bashou tout autre shell qui prend en charge les <(...) substitutions de processus ou vous pouvez l'émuler comme indiqué ici :

diff --new-line-format='FALSE'$'\n' \
     --old-line-format='' \
     --unchanged-line-format='TRUE'$'\n' \
<(nl file1) <(nl file2)

La sortie serait:

TRUE
TRUE
FALSE
FALSE

--new-line-format='FALSE'$'\n, imprimez FALSEsi les lignes étaient différentes et avec --old-line-format=''nous désactivons la sortie si la ligne était différente pour le fichier1 qui est connu sous le nom de l' ancien fichier à la commande diff (nous pourrions également les échanger, ce qui signifie que l'un d'eux devrait imprimer FALSEun autre devrait être désactivé.)

--unchanged-line-format='TRUE'$'\n', imprimer TRUEsi les lignes étaient identiques. la $'\n'syntaxe d'échappement de style C est utilisée pour imprimer une nouvelle ligne après chaque sortie de ligne.

αғsнιη
la source
24

En supposant que les fichiers ne contiennent pas de tabulations:

$ paste file1 file2 | awk -F '\t' '{ print ($1 == $2 ? "TRUE" : "FALSE") }'
TRUE
TRUE
FALSE
FALSE

Cela permet pastede créer deux colonnes délimitées par des tabulations, avec le contenu des deux fichiers dans l'une ou l'autre colonne. La awkcommande compare les deux colonnes sur chaque ligne et imprime TRUEsi les colonnes sont identiques et imprime autrement FALSE.

Kusalananda
la source
10

En supposant que les deux fichiers ont le même nombre de lignes:

awk '{getline f2 < "file2"; print f2 == $0 ? "TRUE" : "FALSE"}' file1

Cela fait une comparaison numérique si les chaînes à comparer sont des nombres et lexicales sinon. Par exemple, 100et 1.0e2serait considéré comme identique. Changez en f2"" == $0pour forcer une comparaison lexicale dans tous les cas.

Selon l' awkimplémentation, la comparaison lexicale se fera comme si en utilisant memcmp()(comparaison octet à octet) ou comme si en utilisant strcoll()(si les deux chaînes triaient de la même manière dans l'ordre de classement des paramètres régionaux). Cela peut faire une différence dans certains paramètres régionaux où l'ordre n'est pas correctement défini pour certains caractères, pas sur toutes les entrées de chiffres décimaux comme dans votre exemple.

Stéphane Chazelas
la source
7

Python 3

with open('file1') as file1, open('file2') as file2:
    for line1, line2 in zip(file1, file2):
        print(line1 == line2)

Production:

True
True
False
False

Si vous en avez besoin TRUEet FALSEen majuscules, remplacez la ligne d'impression par l'une des suivantes:

print(str(line1 == line2).upper())
print('TRUE' if line1 == line2 else 'FALSE')
wjandrea
la source
2
En Python 2, effectuez une import itertoolspremière, puis utilisez à la itertools.izipplace de zip. Sinon, il lira les deux fichiers en mémoire, utilisant peut-être trop de mémoire.
pts
4

Dans bash, lecture de chaque fichier en whileboucle, comparaison des lignes de lecture et impression TRUEou de FALSEmanière appropriée:

while IFS= read -r -u3 line1; IFS= read -r -u4 line2; do
    [[ $line1 == $line2 ]] && echo TRUE || echo FALSE
done 3<file1 4<file2

Les deux appels aux readlectures des descripteurs de fichiers 3 et 4 respectivement. Les fichiers sont redirigés vers ceux-ci avec deux redirections d'entrée dans la boucle.

glenn jackman
la source
0
Tried with awk command and it worked fine


awk 'NR==FNR{a[$1];next}{if ($1 in a){print "TRUE"} else{print "False"}}' file1 file2

production

TRUE
TRUE
False
False
Praveen Kumar BS
la source