Le résultat du diff deux fichiers avec des lignes commutées dit manquer la même ligne deux fois

28

J'essaie de comprendre la commande linux diff sur deux fichiers dont les lignes sont juste une permutation l'une de l'autre mais pas capable de bloquer la sortie qu'elle génère. Considérez les trois commandes ci-dessous:

[myPrompt]$ cat file1
apples
oranges
[myPrompt]$ cat file2 
oranges
apples
[myPrompt]$ diff file1 file2
1d0
< apples
2a2
> apples

Quelqu'un peut-il expliquer la sortie cryptique ci-dessus de diff.

  1. Pourquoi n'y a-t-il aucune mention des "oranges" dans la sortie?
  2. Que signifie 1d0et 2a2signifie?

Je comprends de cette réponse que:

"<" signifie que la ligne est manquante dans le fichier2 et ">" signifie que la ligne est manquante dans le fichier1

MAIS cela n'explique pas pourquoi les oranges manquent dans la sortie.

Geek
la source
12
Parce que orangesc'est la plus grande partie commune entre les deux fichiers, donc ce que vous obtenez est le moyen le plus court pour exprimer les différences entre les deux.
Stéphane Chazelas
10
Et si vous voulez une sortie plus lisible, utilisez simplement à la diff -u file1 file2place. C'est ce qu'on appelle le format "diff unifié". Le format diff d'origine était censé être très compact, mais les différences unifiées sont censées être beaucoup plus lisibles.
godlygeek
4
@godlygeek Ordiff -y file1 file2
user80551

Réponses:

27

Pour comprendre le rapport, n'oubliez pas que diffc'est normatif, décrivant les modifications à apporter au premier fichier ( file1) pour le rendre identique au second fichier ( file2).

Plus précisément, les dau 1d0moyen de supprimer et aà des 2a2moyens d' ajouter .

Ainsi:

  • 1d0signifie que la ligne 1 doit être supprimée entre file1( apples). 0au 1d0moyen ligne 0 est où ils sont apparus dans le second fichier ( file2) étaient - ils pas été supprimés. Cela signifie que lorsque vous passez file2à file1(vers l'arrière), ajoutez la ligne 1 file1après la ligne 0 file2.
  • 2a2signifie ajouter la deuxième ligne ( oranges) de file2à la deuxième ligne de file1(après la suppression de la première ligne file1, orangesbasculée sur la ligne 1)
le chaos
la source
ce qui est 0en 1d0?
Geek
@Geek voir mon montage
chaos
1
@Geek Mais attention, cela peut faire des nœuds dans le cerveau =)
chaos
qui a en effet commencé à faire des nœuds :-)
Geek
13

Considérez ces fichiers:

file1:

# cat file1
apples
pears
oranges
peaches

file2:

# cat file2
oranges
apples
peaches
ananas
banana

Comment cela difffonctionne, étant donné qu'il est basé sur les commandes:

  1. difflit le premier bloc de lignes de file1et file2, et essaie de trouver des lignes égales:

      file1        file2        differences on left (<) or right side (>)
      apples                   <apples
      pears                    <pears 
      -------------------------------
    ->oranges    ->oranges
      peaches      apples
                   peaches
                   ananas
                   banana
    
  2. Maintenant, il sautera toutes les lignes qui sont égales dans les deux fichiers, ce qui est juste orangesdans ce cas:

      file1        file2        differences on left (<) or right side (>)
      apples                   <apples
      pears                    <pears 
      oranges      oranges
      -------------------------------
    ->peaches    ->apples
                   peaches
                   ananas
                   banana
    
  3. Maintenant, trouvez un autre ensemble de lignes similaires et imprimez les différences:

      file1        file2        differences on left (<) or right side (>)
      apples                   <apples
      pears                    <pears 
      oranges      oranges
                   apples      >apples
      -------------------------------
    ->peaches    ->peaches
                   ananas
                   banana
    
  4. Évitez les lignes similaires

      file1        file2        differences on left (<) or right side (>)
      apples                   <apples
      pears                    <pears 
      oranges      oranges
                   apples      >apples
      peaches      peaches
      -------------------------------
    ->           ->ananas
                   banana
    
  5. Si possible, recherchez des lignes identiques et imprimez les différences:

    line_file1    file1    line_file2    file2        differences on left (<) or right side (>)
             1    apples                              <apples 
             2    pears                               <pears 
             3    oranges           1    oranges
                                    2    apples       >apples
             4    peaches           3    peaches
                                    4    ananas       >ananas
                                    5    banana       >banana
             -----------------------------------------------
    

Maintenant, si je le fais diff file1 file2:

# diff file1 file2
1,2d0
< apples
< pears
3a2
> apples
4a4,5
> ananas
> banana

Maintenant, il est simple d'expliquer ce que diffsignifie la sortie:

Pour rendre file1égal à file2:

  • 1,2d0: Supprimer lesd lignes 1-2de ( ) file1et modifier la ligne 0de en file2conséquence
  • 3a2: Ajouter ( a) à la ligne 3de file1ligne 2defile2
  • 4a4,5: Ajouter à la ligne 4de file1lignes 4-5defile2

diffcompare file1avec la file2ligne par des différences de lignes et se dépose dans la mémoire temporaire. Après avoir file1 égal à file2 jusqu'à la première occurrence d'une ligne dans file1, qui se produit également dans file2, toutes les lignes qui sont égales jusqu'à ce qu'une différence ne soit pas mentionnée, sont souvent indiquées par ---. Dans ce cas, il n'y a qu'une seule ligne similaire, qui est oranges. Notez que j'ai dit file1égal à file2, il file1est donc considéré par rapport à file2et non l'inverse.

La sortie est en relation avec le premier fichier donné, dans ce cas file1.

polym
la source
2
Je n'aime pas l'explication initiale: applesse produit aussi bien dans les deux fichiers.
OR Mapper du
1
@ORMapper J'ai changé l'explication. Cela semble-t-il plus clair / meilleur maintenant :)?
polym
Pas tout à fait, pour l'instant vous avez écrit "il n'y a qu'une seule ligne similaire, qui est oranges". Faux: Il y a en fait deux lignes, qui sont non seulement similaires , mais absolument identiques . L' un d'eux lit oranges, l'autre lit apples. De plus, votre explication (purement basée sur l'ordre) est en contradiction avec le commentaire de Stéphane sur la question (basé sur la longueur) - qui a raison?
OR Mapper du
@ORMapper Vous avez oublié "Dans ce cas" et les lignes avant cela. Je voulais dire que dans cette étape, il n'y a qu'une seule ligne similaire. Je vais simplement ajouter un exemple à ma réponse afin qu'elle soit mieux comprise.
polym
1
@ORMapper Pouvez-vous également me donner un exemple qui montre que la réponse basée sur la longueur est correcte?
polym
8

Ils sont là:

$ diff file1 file2
1d0
< apples
2a2
> apples
$ diff file2 file1
1d0
< oranges
2a2
> oranges
user78677
la source
8

Le format de sortie standard (ancien) affichera la différence entre les fichiers sans entourer le texte avec les zones où les fichiers diffèrent.

Par exemple: 1d0 <(supprimer) signifie que les pommes doivent être supprimées de la 1ère ligne de file1, et 2a2 >(ajouter) signifie que les pommes doivent être ajoutées file2sur la 2ème ligne, afin que les deux fichiers puissent être appariés.

La documentation disponible sur info diffexplique plus en détail:

Affichage des différences sans contexte

Le diffformat de sortie "normal" montre chaque morceau de différences sans aucun contexte environnant. Parfois, une telle sortie est le moyen le plus clair de voir comment les lignes ont changé, sans l'encombrement des lignes inchangées à proximité (bien que vous puissiez obtenir des résultats similaires avec le contexte ou les formats unifiés en utilisant 0 lignes de contexte). Cependant, ce format n'est plus largement utilisé pour l'envoi de correctifs; à cet effet, le format de contexte et le format unifié sont supérieurs. Le format normal est la valeur par défaut pour la compatibilité avec les anciennes versions de diffet la norme POSIX. Utilisez l' --normaloption pour sélectionner explicitement ce format de sortie.

Description détaillée du format normal

Le format de sortie normal consiste en un ou plusieurs morceaux de différences; chaque morceau montre une zone où les fichiers diffèrent. Les mecs au format normal ressemblent à ceci:

 CHANGE-COMMAND
 < FROM-FILE-LINE
 < FROM-FILE-LINE...
 ---
 > TO-FILE-LINE
 > TO-FILE-LINE...

Il existe trois types de commandes de modification. Chacun se compose d'un numéro de ligne ou d'une plage de lignes séparées par des virgules dans le premier fichier, d'un caractère unique indiquant le type de modification à effectuer et d'un numéro de ligne ou d'une plage de lignes séparées par des virgules dans le second fichier. Tous les numéros de ligne sont les numéros de ligne d'origine de chaque fichier. Les types de commandes de modification sont les suivants:

LaR Ajoutez les lignes dans la plage R du deuxième fichier après la ligne L du premier fichier. Par exemple, 8a12,15signifie ajouter les lignes 12 à 15 du fichier 2 après la ligne 8 du fichier 1; ou, si vous changez le fichier 2 en fichier 1, supprimez les lignes 12-15 du fichier 2.

FcT Remplacez les lignes de la plage F du premier fichier par des lignes de la plage T du deuxième fichier. C'est comme un ajout et une suppression combinés, mais plus compact. Par exemple, 5,7c8,10signifie changer les lignes 5-7 du fichier 1 pour lire comme les lignes 8-10 du fichier 2; ou, si vous changez le fichier 2 en fichier 1, changez les lignes 8-10 du fichier 2 pour lire comme les lignes 5-7 du fichier 1.

RdL Supprimez les lignes de la plage R du premier fichier; la ligne L est l'endroit où ils seraient apparus dans le deuxième fichier s'ils n'avaient pas été supprimés. Par exemple, 5,7d3signifie supprimer les lignes 5 à 7 du fichier 1; ou, si vous changez le fichier 2 en fichier 1, ajoutez les lignes 5 à 7 du fichier 1 après la ligne 3 du fichier 2.

Voir également:


Donc, pour voir les oranges, il faudrait les différencier côte à côte ou en utilisant un contexte unifié.

Par exemple:

$ diff -y file1 file2
apples                                <
oranges                             oranges
                                  > apples

$ diff -u file1 file2
@@ -1,2 +1,2 @@
-apples
 oranges
+apples
kenorb
la source