'diff'(またはその他)を使用してテキストファイル間の文字レベルの差分を取得する


91

「diff」を使用して、行の違いと文字の違いの両方を取得したいと思います。たとえば、次のことを考慮してください。

ファイル1

abcde
abc
abcccd

ファイル2

abcde
ab
abccc

diff -uを使用すると、次のようになります。

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

ただし、これらの行の変更があったことのみを示しています。私が見たいのは次のようなものです:

@@ -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

あなたは私のドリフトを得る。

これで、他のエンジンを使用して特定の行の違いをマーク/チェックできることがわかりました。しかし、私はむしろそれをすべて行う1つのツールを使用したいと思います。


2
charごとのdiffは、単語分割に空白が適用されないCJKテキストの場合に特に便利です。
把友情留在無盐2015年

回答:


72

Gitには単語の差分があり、すべての文字を単語として定義すると、効果的に文字の差分が得られます。ただし、改行の変更は無視されます。

次のようなリポジトリを作成します。

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

さあ、そうgit diff --word-diff=color --word-diff-regex=. master^ masterすればあなたは得るでしょう:

git diff

追加と削除の両方が文字レベルで認識されることに注意してください。一方、改行の追加と削除はどちらも無視されます。

次のいずれかを試すこともできます。

git diff --word-diff=plain --word-diff-regex=. master^ master
git diff --word-diff=porcelain --word-diff-regex=. master^ master

73
リポジトリを作成する必要はまったくありません。ファイルシステムの任意の場所にある2つのファイルにgit diffを指定するだけで機能します。あなたのコマンドはそのように私にとって素晴らしい働きをするので、ありがとう!git diff --word-diff=color --word-diff-regex=. file1 file2
qwertzguy 2016年

1
これは非常に役立ちます。できれば、ソフトウェア開発者として+1し、作者/作家として+1します。行がかなり短くなる傾向があるコードとは異なり、論文/物語を書くとき、各段落は長い折り返された行の形をとる傾向があり、この機能はdiffを実際に視覚的に有用にします。
mtraceur 2016年

28
--no-indexgitリポジトリの外で動作させるために、上記のto @ qwertzguysの応答を追加する必要がありました。だから:git diff --no-index --word-diff=color --word-diff-regex=. file1 file2
ネイサンベル

2
git diffは一般設定では機能しません:git diff --no-index --word-diff = color --word-diff-regex =。<(echo string1)<(echo string2)..何もありませんが、これは機能します:diff --color <(echo string1)<(echo string2)。
mosh

1
@NathanBell私--no-indexもレポの中に追加する必要がありました
JShorthouse '16

32

以下を使用できます。

diff -u f1 f2 |colordiff |diff-highlight

スクリーンショット

colordiffUbuntuパッケージです。を使用してインストールできsudo apt-get install colordiffます。

diff-highlightgitからです(バージョン2.9以降)。にあります/usr/share/doc/git/contrib/diff-highlight/diff-highlight。あなたはあなたのどこかにそれを置くことができます$PATH


6
colordiffは、Mac用の自作でもご覧になれます。brew install colordiff
エミルStenström

5
Macでは、あなたは見つけることができますdiff-highlight$(brew --prefix git)/share/git-core/contrib/diff-highlight/diff-highlight
StefanoP

2
brewを使用してgitをインストールしなかった場合diff-highlight-pythonのpipでもインストールできます- pip install diff-highlight(gitがbrewでインストールされている場合でも、私はそれを好みます)
Yaron U.

21

プログラムでこれを実行する場合、Pythonのdifflib最適です。インタラクティブな使用のために、私はvimの diffモードを使用します(使用するのに十分簡単です:でvimを呼び出すだけvimdiff a bです)。私は時々Beyond Compareも使用します。BeyondCompareは、diffツールから期待できるほとんどすべてのことを行います。

これを効果的に実行するコマンドラインツールはありませんが、Willが指摘するように、difflibのサンプルコードが役立つ場合があります。


1
ああ..(非表示のコマンドライン引数など)より標準化されたものを期待していた。ひどいのは、Beyond Compare 2があり、diffのファイル/コンソールへのテキスト出力もサポートしていることですが、char-diffではなくline-diffしか含まれていません。他に誰もいない場合は、Pythonを調べます。
VitalyB 2009年

6
vimdiffを紹介してくれた+1。デフォルトの色が判読できないことがわかりましたが、その解決策がstackoverflow.com/questions/2019281/…にありました
未定義

17

cmpSolarisで次のコマンドを使用できます。

cmp

2つのファイルを比較し、異なる場合は、最初のバイトと行番号が異なる場所を示します。


2
cmp(少なくとも一部の)Linuxディストリビューションでも利用できます。
Jeff Evans

7
これは、Mac OS X上でも利用可能だ
エリックR.ラース

文字は複数のバイトで構成でき、OPは視覚的な比較を求めました。
Cees Timmerman、

1
@CeesTimmerman:cmpでは、フラグを使用して視覚的に比較できます-l -b
Smar

9

Pythonにはdifflib、質問への回答に役立つという名前の便利なライブラリがあります。

以下はdifflib、異なるPythonバージョンで使用する2つのoneliners です。

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()))'

これらは、と一緒に移動しやすいシェルエイリアスとして役立つ場合があります.${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

スタンドアロンファイルに配置する、より読みやすいバージョン。

#!/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)

ワンライナーに優れています。変更されていない行を無視する圧縮された出力があると便利です。
aidan.plenert.macdonald 2017

6
cmp -l file1 file2 | wc

私にとってはうまくいきました。結果の左端の数字は、異なる文字の数を示します。


1
それとも、左端の番号を取得する:cmp -l file1 file2 | wc -l
トニー・

5

また、Longest common subsequenceアルゴリズムを使用してこの問題を解決するために、独自のスクリプト作成しました

そのように実行されます

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

結果は、赤と緑の色が付いたhtmlになります。ファイルが大きくなると、指数関数的に処理に時間がかかりますが、行ごとに最初にチェックすることなく、文字ごとの比較が行われます。


JLDiffはpypyではるかに高速に実行されることを発見しました。
Joshua

4

着色、文字レベル diff出力に含ま

以下のスクリプトとdiff-highlight(gitの一部)でできることは次のとおりです。

色付きの相違のスクリーンショット

#!/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

(強調表示のための@retracileの回答のクレジットsed


シェル画面に良い差分が表示されますが、GVimでその差分を確認するにはどうすればよいですか?
Hemant Sharma 2017年

1
それが本当にgvimの質問なのか:) command | gvim -あなたがしたいことをします。
肥満児RIGH

参考のために、diff-highlightはgitパスの一部として含まれているように見えますが、パスには配置されていません。これが私のマシンの1つ/usr/share/doc/git/contrib/diff-highlightです。
At Righ

リンク切れ。diff-highlightをインストールするにはどうすればよいですか。パッケージマネージャーにはないようです。
Trevor Hickey 2017

3

Pythonのdifflibはこれを行うことができます。

ドキュメントには、コマンドラインプログラムの例が含まれています。

正確な形式は指定したとおりではありませんが、ndiffスタイルの出力を解析するか、サンプルプログラムを変更して表記を生成するのは簡単です。


ありがとう!調べてみます。私はもっ​​と標準化されたもの(隠されたコマンドライン引数のような)を望んでいました。しかし、それでもまだうまくいくかもしれません。他に標準がない場合は、Pythonを調べます(標準ではないようですが)。
VitalyB 2009年

2

ここにオンラインのテキスト比較ツールがあります:http : //text-compare.com/

異なるすべての文字を強調表示し、残りを比較し続けることができます。


これは単一文字のオプションなしで行レベルの差分を行うようです。どのようにしてキャラクターを比較しますか?
ドラゴン

ああ。異なる文字を強調表示します。しかし、それはまだその中にラインレベルだcatdogcat\ndogのみにマッチしますcat
ドラゴン

1

単純な解決策は常に良い解決策だと思います。私の場合、以下のコードが非常に役立ちます。それが他の人の役に立つことを願っています。

#!/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]

2つのファイルを次の構文でお気に入りのターミナルで比較できます。

$ ./diff.py fileNumber1 fileNumber2

0

ファイルをGitに保持している場合は、異なる行が表示され、違いが強調表示されたdiff-highlightスクリプトを使用して、バージョン間で差分をとることができます。

残念ながら、削除された行数が追加された行数と一致する場合にのみ機能します。行が一致しない場合のスタブコードがあるため、おそらくこれは将来修正される可能性があります。


0

完全な答えではありませんが、cmp -lの出力が十分に明確でない場合は、以下を使用できます。

sed 's/\(.\)/\1\n/g' file1 > file1.vertical
sed 's/\(.\)/\1\n/g' file2 > file2.vertical
diff file1.vertical file2.vertical

OSXでは `` `sed 's /(。)/ \ 1 \' $ '\ n / g' file1> file1.vertical sed 's / \(。\)/ \ 1 \' $ '\ n / g 'file2> file2.vertical `` `
mmacvicar

0

これらの回答のほとんどは、Perlモジュールであるdiff-highlightの使用に言及しています。しかし、Perlモジュールをインストールする方法を理解したくありませんでした。そこで、自己完結型のPerlスクリプトになるように、いくつかの小さな変更を加えました。

次の方法でインストールできます。

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

そして使用法(colordiffzhanxwの答えでUbuntuが言及されている場合):

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

そして、使用方法(そうでない場合):

▶ diff -u f1 f2 | DiffHighlight.pl
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.