web-dev-qa-db-fra.com

Utiliser 'diff' (ou autre chose) pour obtenir des différences au niveau du caractère entre les fichiers texte

J'aimerais utiliser 'diff' pour obtenir une différence de ligne entre et une différence de caractère . Par exemple, considérons:

Fichier 1

abcde
abc
abcccd

Fichier 2

abcde
ab
abccc

En utilisant diff -u je reçois:

@@ -1,3 +1,3 @@
 abcde
-abc
-abcccd
\ No newline at end of file
+ab
+abccc
\ No newline at end of file

Cependant, cela ne fait que me montrer que des modifications ont été apportées à ces lignes. Ce que j'aimerais voir est quelque chose comme:

@@ -1,3 +1,3 @@
 abcde
-ab<ins>c</ins>
-abccc<ins>d</ins>
\ No newline at end of file
+ab
+abccc
\ No newline at end of file

Vous obtenez ma dérive.

Maintenant, je sais que je peux utiliser autres moteurs pour marquer/vérifier la différence sur une ligne spécifique. Mais je préférerais utiliser un outil qui fait tout.

59
VitalyB

Git a un diff Word, et définir tous les caractères en tant que mots vous donne effectivement un diff. Cependant, les changements de nouvelle ligne sont IGNORÉS.

EXEMPLE:

Créez un référentiel comme ceci:

mkdir chardifftest
cd chardifftest
git init
echo -e 'foobarbaz\ncatdog\nfox' > file
git add -A; git commit -m 1
echo -e 'fuobArbas\ncat\ndogfox' > file
git add -A; git commit -m 2

Maintenant, faites git diff --Word-diff=color --Word-diff-regex=. master^ master et vous obtiendrez:

git diff http://oi60.tinypic.com/160wpb4.jpg

Notez comment les ajouts et les suppressions sont reconnus au niveau du caractère, alors que les ajouts et les suppressions de nouvelles lignes sont ignorés.

Vous voudrez peut-être aussi essayer
git diff --Word-diff=plain --Word-diff-regex=. master^ master
et
git diff --Word-diff=porcelain --Word-diff-regex=. master^ master

49
senf78

difflib de Python est un atout si vous voulez le faire par programme. Pour une utilisation interactive, j'utilise le mode vim diff (assez simple à utiliser: il suffit d'appeler vim avec vimdiff a b). J'utilise aussi parfois Beyond Compare , qui fait à peu près tout ce que l'on peut espérer d'un outil diff.

Je n'ai vu aucun outil en ligne de commande qui le fasse utilement, mais comme le note Will, l'exemple de code difflib peut aider.

15
Ned

Vous pouvez utiliser la commande cmp dans Solaris:

cmp

Comparez deux fichiers et, s'ils diffèrent, indique le premier octet et le numéro de ligne où ils diffèrent.

13

Vous pouvez utiliser:

diff -u f1 f2 |colordiff |diff-highlight

 screenshot

colordiff est un paquet Ubuntu. Vous pouvez l'installer avec Sudo apt-get install colordiff.

diff-highlight provient de git (depuis la version 2.9). Il est situé dans /usr/share/doc/git/contrib/diff-highlight/diff-highlight. Vous pouvez le mettre quelque part dans votre $PATH. Ou l'obtenir de projet diff-so-fantaisie .

12
zhanxw

Python a une bibliothèque pratique nommée difflib qui pourrait aider à répondre à votre question.

Vous trouverez ci-dessous deux exemples utilisant difflib pour différentes versions de python.

python3 -c 'import difflib, sys; \
  print("".join( \
    difflib.ndiff( \ 
      open(sys.argv[1]).readlines(),open(sys.argv[2]).readlines())))'
python2 -c 'import difflib, sys; \
  print "".join( \
    difflib.ndiff( \
      open(sys.argv[1]).readlines(), open(sys.argv[2]).readlines()))'

Ceux-ci peuvent s'avérer utiles sous la forme d'un alias Shell qui est plus facile à déplacer avec votre .${Shell_NAME}rc.

$ alias char_diff="python2 -c 'import difflib, sys; print \"\".join(difflib.ndiff(open(sys.argv[1]).readlines(), open(sys.argv[2]).readlines()))'"
$ char_diff old_file new_file

Et une version plus lisible à mettre dans un fichier autonome.

#!/usr/bin/env python2
from __future__ import with_statement

import difflib
import sys

with open(sys.argv[1]) as old_f, open(sys.argv[2]) as new_f:
    old_lines, new_lines = old_f.readlines(), new_f.readlines()
diff = difflib.ndiff(old_lines, new_lines)
print ''.join(diff)
5
Mr. Deathless

J'ai également écrit mon script own pour résoudre ce problème à l'aide de l'algorithme de sous-séquence commun le plus long.

Il est exécuté comme tel

JLDiff.py a.txt b.txt out.html

Le résultat est en html avec une coloration rouge et verte. Le traitement des fichiers volumineux prend de manière exponentielle une durée plus longue, mais cela permet une comparaison vraie caractère par caractère sans vérification ligne par ligne en premier.

3
Joshua
cmp -l file1 file2 | wc

A bien fonctionné pour moi. Le nombre le plus à gauche du résultat indique le nombre de caractères différents.

3
Chris Prince

Couleur, niveau du caractèrediff ouput

Voici ce que vous pouvez faire avec le script ci-dessous et diff-highlight (qui fait partie de git):

 Coloured diff screenshot

#!/bin/sh -eu

# Use diff-highlight to show Word-level differences

diff -U3 --minimal "$@" |
  sed 's/^-/\x1b[1;31m-/;s/^+/\x1b[1;32m+/;s/^@/\x1b[1;34m@/;s/$/\x1b[0m/' |
  diff-highlight

(Merci à la réponse de @ retracile pour la surbrillance sed)

3
Tom Hale

Le difflib de Python peut le faire.

La documentation comprend un exemple programme en ligne de commande pour vous.

Le format exact n’est pas celui que vous avez spécifié, mais il serait simple d’analyser la sortie de type ndiff ou de modifier le programme exemple pour générer votre notation.

2
Will

Voici un outil de comparaison de texte en ligne: http://text-compare.com/

Il peut mettre en évidence chaque caractère différent et continuer à comparer le reste.

2
gm2008

Je pense que la solution la plus simple est toujours une bonne solution ..__ Dans mon cas, le code ci-dessous m'aide beaucoup J'espère que cela aide Quelqu'un d'autre.

#!/bin/env python

def readfile( fileName ):
    f = open( fileName )
    c = f.read()
    f.close()
    return c

def diff( s1, s2 ):
    counter=0
    for ch1, ch2 in Zip( s1, s2 ):
        if not ch1 == ch2:
            break
        counter+=1
    return counter < len( s1 ) and counter or -1

import sys

f1 = readfile( sys.argv[1] )
f2 = readfile( sys.argv[2] )
pos = diff( f1, f2 )
end = pos+200

if pos >= 0:
    print "Different at:", pos
    print ">", f1[pos:end]
    print "<", f2[pos:end]

Vous pouvez comparer deux fichiers avec la syntaxe suivante sur votre terminal préféré:

$ ./diff.py fileNumber1 fileNumber2
1
Miere

La plupart de ces réponses mentionnent l'utilisation de diff-highlight , un module Perl. Mais je ne voulais pas savoir comment installer un module Perl. J'ai donc apporté quelques modifications mineures à ce script pour qu'il devienne un script Perl autonome.

Vous pouvez l'installer en utilisant:

▶ curl -o /usr/local/bin/DiffHighlight.pl \
   https://raw.githubusercontent.com/alexharv074/scripts/master/DiffHighlight.pl

Et l'utilisation (si vous avez la colordiff Ubuntu mentionnée dans la réponse de zhanxw):

▶ diff -u f1 f2 | colordiff | DiffHighlight.pl

Et l'usage (si vous ne le faites pas):

▶ diff -u f1 f2 | DiffHighlight.pl
0
Alex Harvey

Si vous conservez vos fichiers dans Git, vous pouvez différencier les versions avec le script diff-highlight , qui affichera différentes lignes, les différences étant mises en évidence. 

Malheureusement, cela ne fonctionne que lorsque le nombre de lignes supprimées correspond au nombre de lignes ajoutées - il existe un code de raccord pour les cas où les lignes ne correspondent pas. Par conséquent, cela pourrait probablement être résolu ultérieurement.

0
naught101

Pas une réponse complète, mais si la sortie de cmp -l n'est pas assez claire, vous pouvez utiliser:

sed 's/\(.\)/\1\n/g' file1 > file1.vertical
sed 's/\(.\)/\1\n/g' file2 > file2.vertical
diff file1.vertical file2.vertical
0
sudo rm -rf slash