使用“差异”(或其他任何方式)获取文本文件之间的字符级差异


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

你让我流连忘返。

现在,我知道我可以使用其他引擎来标记/检查特定行上的差异。但是我宁愿使用一种工具来完成所有这些工作。


2
per char diff在涉及CJK文本时特别有用,在CJK文本中,没有空格用于分词。
把友情留在无盐2015年

Answers:


72

Git有一个单词diff,将所有字符定义为单词会有效地给您一个字符diff。但是,新行更改将被忽略

创建一个这样的存储库:

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
您根本不需要创建存储库,只需在文件系统上的任何位置为git diff提供任意两个文件,它就可以工作。这样,您的命令对我非常有用,谢谢!git diff --word-diff=color --word-diff-regex=. file1 file2
qwertzguy

1
这非常有帮助!如果可以的话,我会以软件开发人员的身份+1一次,以作家/作家的身份+1两次。与代码中的行往往相当短的代码不同,在撰写论文/故事时,每个段落都倾向于采用长条文字换行的形式,并且此功能使差异实际上在视觉上很有用。
mtraceur '16

28
我需要在上面添加--no-indexto @ qwertzguys的响应,以使其在git repo之外对我有用。所以: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,

32

您可以使用:

diff -u f1 f2 |colordiff |diff-highlight

屏幕截图

colordiff是Ubuntu软件包。您可以使用安装它sudo apt-get install colordiff

diff-highlight来自git(从2.9版开始)。它位于中/usr/share/doc/git/contrib/diff-highlight/diff-highlight。您可以将其放在您的计算机中的某个位置$PATH


6
在Mac上的自制软件上也可以使用colordiff:brew install colordiff
EmilStenström19年

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(即使通过brew安装git,我也更喜欢)
Yaron

21

如果要以编程方式执行此操作,则Python的difflib是ace。对于交互式使用,我使用vim的 diff模式(易于使用:只需使用调用vim vimdiff a b)。我也偶尔使用Beyond Compare,它几乎可以完成diff工具所希望的一切。

我还没有看到任何命令行工具可以有效地执行此操作,但是正如Will所指出的,difflib示例代码可能会有所帮助。


1
哦..我希望有一些更标准化的东西(例如隐藏的命令行参数)。最可恶的是,我拥有Beyond Compare 2,它甚至还支持将文本输出到diff的文件/控制台,但它仍然仅包含line-diffs,而不包含char-diffs。如果没有其他任何内容,我将调查python。
VitalyB,2009年

6
+1向我介绍vimdiff。我发现默认颜色不可读,但在stackoverflow.com/questions/2019281/…处找到了解决方案。
undefined

17

您可以cmp在Solaris中使用该命令:

cmp

比较两个文件,如果它们不同,则告诉第一个字节和行号不同的地方。


2
cmp在(至少某些)Linux发行版中也可用。
杰夫·埃文斯

7
它也可以在Mac OS X
Eric R. Rath

字符可以包含多个字节,OP要求进行视觉比较。
Cees Timmerman

1
@CeesTimmerman:cmp允许带有flag的视觉比较-l -b
Smar

9

Python有一个方便的库difflib,它可以帮助您回答问题。

以下是difflib用于不同python版本的两个oneliner 。

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别名可能会派上用场,它更容易随您的一起移动.${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

6
cmp -l file1 file2 | wc

对我来说很好。结果的最左侧数字表示不同的字符数。


1
或仅获取最左边的数字:cmp -l file1 file2 | wc -l
托尼

5

我还编写了自己的脚本,以使用最长公共子序列算法解决此问题

这样执行

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

结果是带有红色和绿色的html格式。较大的文件确实需要花费更长的时间才能处理,但这确实可以进行逐字符比较,而无需先逐行检查。


我发现JLDiff在pypy下运行更快。
约书亚

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中看到差异?
赫曼·夏尔马

1
这实际上是一个gvim问题:)。command | gvim -会做你想要的。
Att Righ

作为参考,diff-highlight似乎已包含git在路径中,但未放置在路径中。我的一台机器的寿命在/usr/share/doc/git/contrib/diff-highlight
Att Righ

链接断开。如何安装diff-highlight。似乎不在包管理器中。
Trevor Hickey

3

Python的difflib可以做到这一点。

该文档包括一个示例命令行程序

确切的格式不是您指定的格式,但是解析ndiff样式的输出或修改示例程序以生成您的符号将很简单。


谢谢!我会调查一下。我希望有一些更标准化的东西(例如隐藏的命令行参数)。但这可能仍然很好。如果没有人拥有更多标准,我将研究python(尽管似乎没有)。
VitalyB,2009年

2

这是一个在线文本比较工具:http : //text-compare.com/

它可以突出显示每个不同的字符,并继续比较其余字符。


这似乎是行级差异,单个字符没有选项。如何获得比较字符的信息?
2014年

啊; 它突出显示不同的字符。但是它仍然是线水平的,catdog并且cat\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]

您可以在自己喜欢的终端上使用以下语法比较两个文件:

$ ./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 '文件2> file2.vertical```
mmacvicar

0

这些答案大多数都提到了diff-highlight的使用了Perl模块的使用。但是我不想弄清楚如何安装Perl模块。因此,我对其进行了一些小的更改,以使其成为一个独立的Perl脚本。

您可以使用以下方法安装它:

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

以及用法(如果您colordiff在zhanxw的答案中提到了Ubuntu ):

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

和用法(如果您不这样做):

▶ diff -u f1 f2 | DiffHighlight.pl
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.