Différence d'espaces entre deux fichiers sous Linux

15

J'ai deux fichiers qui, lorsque je compare avec diff, montrent que chaque ligne a changé. Lorsque je les compare avec diff -w(en ignorant les espaces blancs), cela montre les quelques changements minimes que j'attends.

Évidemment, il y a une certaine différence entre les espaces dans chaque fichier, mais je ne sais pas ce qu'ils sont ni comment les trouver. J'ai essayé d'éditer les fichiers pour m'assurer que l'espace est en fait des caractères d'espacement (par opposition aux tabulations) mais je ne sais pas quoi faire d'autre.

J'ai utilisé vim avec :set list onpour confirmer qu'il n'y avait pas d'espace de fuite à la fin des lignes.

Je crois également que chaque fichier a des terminateurs de ligne Linux car vim n'affiche pas le ^Mà la fin des lignes.

Romski
la source
1
Avez-vous vérifié la présence d'espaces en fin de ligne (à la fin d'une ligne)? Un tel espace sera détecté par diffmais de nombreux éditeurs ne rendent pas, par défaut de toute façon, cet espace visible.
John1024
Bonne suggestion. J'ai utilisé vim avec ": set list on" cela montrait le "$" à la fin de la ligne et il n'y avait pas d'espace de fin. Je mettrai à jour ma question
Romski
Si vous êtes un vimutilisateur, avez-vous essayé d'utiliser vimdiff file1 file2pour voir quelles sont les différences?
John1024
@ John1024 Je n'étais pas au courant de vimdiff, mais cela semble prometteur. Ajoutez-le comme réponse et j'accepterai
Romski
1
Vim affiche ^ M uniquement lorsqu'il détecte mal une fin de ligne Unix mais que le fichier a en fait une fin de ligne DOS. Cela se produit généralement si vous avez une ligne mixte se terminant dans un seul fichier, par exemple en appliquant un correctif avec une fin de ligne différente de celle du fichier d'origine. Lorsque vim détecte que la ligne DOS se termine correctement, il n'affiche pas le ^ M.
Lie Ryan

Réponses:

7

Pour les vimutilisateurs, il existe un utilitaire pratique pour afficher les différences exactes entre les fichiers:

vimdiff file1 file2

Cela mettra chaque fichier dans les fenêtres, côte à côte et les différences seront mises en évidence en couleur.

Quelques commandes utiles en vimdiff

Une fois dans vimdiff, certaines commandes utiles sont:

  • ]c: passer au prochain changement

  • [c: passer au changement précédent

  • ctrl-W ctrl-W: passer à une autre fenêtre

  • zo: plis ouverts

  • zc: fermer les plis

Exemple

Voici un exemple de vimdiffdans un xtermdeux versions comparant d'un cupsfichier de configuration:

entrez la description de l'image ici

Vous pouvez voir que de longues sections de lignes identiques ont été réduites. Ils peuvent être rouverts avec zo.

Le jeu de couleurs varie en fonction des paramètres de votre option. Dans l'exemple ci-dessus, lorsqu'une ligne apparaît dans un fichier mais pas dans l'autre, cette ligne reçoit un arrière-plan bleu foncé. Dans l'autre fichier, les lignes manquantes sont indiquées par des lignes en pointillés. Lorsqu'une ligne apparaît dans les deux fichiers mais présente quelques différences, les parties inchangées des lignes ont un fond rose et les parties modifiées ont un fond rouge.

John1024
la source
14

Sur FreeBSD ou la plupart des systèmes Linux, vous pouvez diriger la sortie de diff via cat -v -e -tpour afficher les différences d'espaces.

diff file1 file2 | cat -vet

Les onglets seront affichés comme ^I, un $sera affiché à la fin de chaque ligne afin que vous puissiez voir les espaces de fin, et les caractères non imprimables seront affichés comme ^Xou M-X.

Si vous avez des coreutils GNU (disponibles sur la plupart des distributions Linux non occupées), cela peut être simplifié pour

diff file1 file2 | cat -A

Sur les systèmes busybox, utilisez catv -vet.

Mark Plotnick
la source
2

L'un des fichiers a-t-il été modifié sur une machine Windows?

La terminaison de ligne standard sous Windows est CRLF, où sous Linux c'est simplement LF (et sur Mac c'était CR, mais je suppose que cela a changé depuis OS X).

Essayez wc -lles fichiers et voyez combien de lignes, puis voyez si la différence de taille est la même que le nombre de lignes (la dernière ligne peut ne pas se terminer dans un fichier).

poteau de clôture
la source
Merci pour la réponse rapide. Faire un décompte de lignes montre qu'un fichier a 5 lignes de plus (je m'attends à ce que j'ai fait des modifications). J'ai obtenu un fichier d'une machine Linux et l'autre a été extrait d'un référentiel de code sur Linux. Je crois que l'affichage d'un fichier avec les terminateurs Windows dans vim affichera le dernier caractère comme ^ M et ce n'est pas le cas.
Romski
3
vim est en fait assez intelligent pour détecter automatiquement la terminaison de ligne, voir stackoverflow.com/questions/3852868 pour plus de détails.
fencepost
Je n'étais pas au courant de ça! Je revérifierai
Romski le
2

odpeut aider. La commande Octal Dump peut afficher le contenu en hexadécimal. Cela peut vous aider à voir quels octets, y compris les octets nuls ou les espaces blancs inattendus, se trouvent dans un fichier. Les causes courantes possibles peuvent être LF vs CRLF, tabulations vs espaces ou ASCII vs Unicode (qui peuvent souvent avoir juste un octet nul avant chaque octet normalement visible). od -x filenamedevrait révéler l'un de ces modèles. Si vous voulez une manière plus élaborée d'afficher le fichier, n'importe quel "éditeur hexadécimal" peut très bien fonctionner. Ce odqui est bien, c'est que, comme la cutcommande, elle est intégrée à de nombreux systèmes Unix. Ainsi, souvent, aucune installation séparée n'est nécessaire.

Si vous avez besoin que les fichiers soient plus similaires, vous trpouvez apporter des modifications et en sedfaire plus. Je commencerais probablement par ls -lvoir quel fichier est plus grand, puis afficher les octets pour voir ce qui doit être changé, puis changer l'un des fichiers afin qu'ils semblent plus similaires.

TOOGAM
la source
1

Pour savoir où se trouvent les vrais espaces et onglets, vous pouvez les remplacer en utilisant sedpar exemple:

$ cat file
  line 1
  line 2
    line 6
        line 7
$ sed 's/ /-/g; s/\t/<tab>/g' file
--line-1
--line-2
<tab>line-6
<tab><tab>line-7

Et maintenant, comparez les deux fichiers.

le chaos
la source
Encore mieux, vous pouvez exécuter ce filtre sur la sortie diff. Ou vous pouvez utiliser le filtre prêt à l'emploi cat, comme dans superuser.com/a/913368/37154
clacke
0

Le contenu suivant a été copié ici à partir de la section "question" ci-dessus, qui a été écrite par Romski.

Les deux vimdiffet diff file1 file2 | cat -Aétaient très utiles du point de vue des outils.

Enfin, j'ai trouvé un autre problème. Certains de mes fichiers ont été encodés avec la nomenclature UTF-8. Cela a été mis en évidence à l'aide de diff file1 file2 | cat -A. Cela s'est manifesté comme M-oM-;M-?au début du fichier affecté:

$ diff file1 file2 | cat -A
< package com.mycompany;$
---$
> M-oM-;M-?package com.mycompany;$

Bien qu'il y ait eu un certain nombre de problèmes, j'ai énuméré quelques commandes ci-dessous pour ceux qui ont besoin de nettoyer leurs fichiers:

# recursively remove UTF8 BOM
find . -type f -exec sed -i -e '1s/^\xEF\xBB\xBF//' {} \;

# recursively replace CRLF with LF
find . -type f -print0 | xargs -0 dos2unix
Kevin Panko
la source