105 votes

Comment faire pour que diff n'affiche que les lignes ajoutées et supprimées ? Si diff ne peut pas le faire, quel outil le peut ?

Comment faire pour que diff n'affiche que les lignes ajoutées et supprimées ? Si diff ne peut pas le faire, quel outil le peut ?

2 votes

Vous devez mieux définir ce que vous entendez par ajout et suppression. Plus précisément, une ligne peut-elle changer ? Si oui, comment voulez-vous qu'une ligne modifiée soit traitée ? Si vous effectuez une vérification strictement axée sur les lignes, une ligne qui change est identique à l'ancienne ligne qui est supprimée et à la nouvelle ligne qui est ajoutée. Par exemple, comment doit-il traiter une ligne qui est divisée en deux ? Comme deux 1 ligne changée ? 2 lignes modifiées ? 1 ligne supprimée et 2 lignes ajoutées ? A moins que vous puissiez garantir que les lignes ne changeront jamais, qu'elles seront juste ajoutées et supprimées, je pense que c'est voué à l'échec sans de meilleures définitions.

2 votes

Je trouve la question assez peu claire. Mais au moins une interprétation de la question pourrait être répondue par diff A B | grep '^[<>]'

0 votes

Vous recherchez peut-être comm .

125voto

Anatidaus Points 2549

Essayez de comm

Une autre façon de voir les choses :

  • Afficher les lignes qui n'existent que dans le fichier a : (c'est-à-dire ce qui a été supprimé de a)

      comm -23 a b
  • Afficher les lignes qui n'existent que dans le fichier b : (c'est-à-dire ce qui a été ajouté à b)

      comm -13 a b
  • Afficher les lignes qui n'existent que dans un fichier ou l'autre : (mais pas dans les deux)

      comm -3 a b | sed 's/^\t//'

(Avertissement : Si le fichier a a des lignes qui commencent par TAB, il (le premier TAB) sera supprimé de la sortie).

Fichiers triés uniquement

NOTE : Les deux fichiers doivent être triés pour comm pour fonctionner correctement. S'ils ne le sont pas déjà, vous devriez les trier :

sort <a >a.sorted
sort <b >b.sorted
comm -12 a.sorted b.sorted

Si les fichiers sont extrêmement longs, cela peut représenter une charge importante car cela nécessite une copie supplémentaire et donc deux fois plus d'espace disque.

5 votes

Je voulais juste ajouter que les deux fichiers doivent être triés (en respectant la casse) pour que cette solution produise des résultats corrects.

2 votes

Sur les shells assez modernes, vous pouvez trier en ligne avec quelque chose comme comm -12 <(sort a) <(sort b)

1 votes

Wow, une nouvelle commande linux, merci. Ça n'arrive plus beaucoup.

23voto

iphonedroid Points 281

Pour afficher les ajouts et les suppressions sans contexte, sans numéro de ligne, sans +, -, <, > ! etc, vous pouvez utiliser diff comme ceci :

diff --changed-group-format='%<%>' --unchanged-group-format='' a.txt b.txt 

Par exemple, étant donné deux fichiers :

a.txt

Common
Common
A-ONLY
Common

b.txt

Common
B-ONLY
Common
Common

La commande suivante montrera les lignes retirées de a ou ajoutées à b :

diff --changed-group-format='%<%>' --unchanged-group-format='' a.txt b.txt 

sortie :

B-ONLY
A-ONLY

Cette commande légèrement différente affichera les lignes supprimées de a.txt :

diff --changed-group-format='%<' --unchanged-group-format='' a.txt b.txt 

sortie :

A-ONLY

Enfin, cette commande montrera les lignes ajoutées à a.txt

diff --changed-group-format='%>' --unchanged-group-format='' a.txt b.txt 

sortie

B-ONLY

16voto

MojoFilter Points 3730

comm pourrait faire ce que vous voulez. De sa page de manuel :

DESCRIPTION

Comparez les fichiers triés FILE1 et FILE2 ligne par ligne.

Sans option, produire une sortie en trois colonnes. La première colonne contient les lignes propres au FILE1, la colonne deux contient les lignes propres au FILE2, et la troisième colonne contient les lignes communes aux deux fichiers.

Ces colonnes peuvent être supprimées avec -1 , -2 y -3 respectivement.

Exemple :

[root@dev ~]# cat a
common
shared
unique

[root@dev ~]# cat b
common
individual
shared

[root@dev ~]# comm -3 a b
    individual
unique

Et si vous voulez juste les lignes uniques et ne vous souciez pas du fichier dans lequel elles se trouvent :

[root@dev ~]# comm -3 a b | sed 's/^\t//'
individual
unique

Comme le dit la page de manuel, les fichiers doivent être triés au préalable.

4voto

Seppo Enarvi Points 149

Les outils de comparaison visuelle assemblent deux fichiers de sorte qu'un segment ayant le même nombre de lignes mais un contenu différent sera considéré comme un segment modifié. Les lignes complètement nouvelles entre les segments correspondants sont considérées comme des segments ajoutés.

C'est également ainsi que sdiff fonctionne, qui montre une comparaison côte à côte de deux fichiers dans un terminal. Les lignes modifiées sont séparées par le caractère |. Si une ligne n'existe que dans le fichier A, < est utilisé comme caractère séparateur. Si une ligne n'existe que dans le fichier B, > est utilisé comme séparateur. Si vous n'avez pas de caractères < et > dans les fichiers, vous pouvez utiliser ceci pour afficher uniquement les lignes ajoutées :

sdiff A B | grep '[<>]'

0 votes

sdiff --suppress-common-lines est peut-être ce dont les gens ont besoin ; il comprend | ainsi que < / > des lignes mais c'est exactement ce dont j'avais besoin.

3voto

jason saldo Points 5036

Non, diff ne montre pas réellement les différences entre deux fichiers comme on pourrait le penser. Il produit une séquence de commandes d'édition pour un outil comme patch à utiliser pour transformer un fichier en un autre.

La difficulté pour toute tentative de faire ce que vous recherchez est de définir ce qui constitue une ligne qui a changé par rapport à une ligne supprimée suivie d'une ligne ajoutée. Il faut également savoir ce qu'il faut faire lorsque des lignes sont ajoutées, supprimées et modifiées à côté les unes des autres.

0 votes

C'est exactement ce que je pense. Quel pourcentage de personnages d'une ligne doit changer pour que l'on considère qu'il s'agit d'une nouvelle ligne et non d'une modification de l'originale ? Techniquement, même si vous avez un caractère en commun, vous pouvez le considérer comme une "modification" au lieu d'une suppression et d'une insertion.

1 votes

Cela fait longtemps que je n'ai pas regardé le diff mais il me semble me souvenir de toutes sortes de girations pour garder la trace de l'endroit où deux fichiers correspondent pour rester synchronisés et je pense qu'il y a un seuil pour abandonner en fonction de la distance entre les lignes. Mais je ne me souviens pas d'une quelconque correspondance intra-ligne, à l'exception (facultative) de l'élimination des espaces blancs ou de l'ignorance de la casse. Ou (peut-être) des mots à cet effet. Dans tous les cas, il s'agit de patch et "vgrep" est juste là pour la balade. Peut-être. Mardi.

0 votes

C'est la seule réponse utile sur ce que diff fait, la plupart des gens l'utilisent sans même le tester. Je suis devenu fou avec le résultat de diff, mais maintenant je comprends à quoi sert cet outil.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X