使用“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 

你得到我的漂移。

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

Git有一个单词diff,并将所有字符定义为单词有效地给你一个字符差异。 但是,换行符是IGNORED。

例:

像这样创build一个存储库:

 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 --word-diff=color --word-diff-regex=. master^ master ,你会得到:

git diff 160wpb4.jpg

请注意在字符级别如何识别添加和删除,而忽略新行的添加和删除。

你也可以尝试
git diff --word-diff=plain --word-diff-regex=. master^ master

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

我没有检查python库,但最终发现Google的解决scheme足够我所需要的。 它用很多种语言实现(其中C#)。 令我印象深刻。

Python的difflib是ace,如果你想以编程的方式做到这一点。 对于交互式使用,我使用vim的差异模式(使用起来很简单:只需用vimdiff ab调用vim)。 我还偶尔使用Beyond Compare ,它几乎可以从diff工具中获得所有的希望。

我没有看到任何有用的命令行工具,但是Will会注意到,difflib示例代码可能会有所帮助。

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

cmp

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

您可以使用:

 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某个地方。 或者从差异化的项目中获得 。

Python有一个名为difflib方便的库,可以帮助你回答你的问题。

下面是两个使用difflib的python版本的difflib

 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) 
 cmp -l file1 file2 | wc 

为我工作得很好。 结果的最左边的数字表示不同的字符数。

我也写了我自己的脚本来解决这个问题,使用最长的公共子序列algorithm。

它是这样执行的

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

结果是HTML与红色和绿色的着色。 较大的文件确实需要花费较长的时间来处理,但是通过字符比较确实是一个真正的字符,而不是逐行检查。

Python的difflib可以做到这一点。

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

确切的格式不像您指定的那样,但是可以直接parsingndiff风格的输出或修改示例程序来生成符号。

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

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

有色, 字符级别的 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 

( 感谢@ retraceile对sed突出显示的回答 )

我认为更简单的解决scheme总是一个很好的解决scheme。 在我的情况下,下面的代码帮助了我很多。 我希望它能帮助其他人。

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

您可以在您喜爱的terminal上使用以下语法比较两个文件:

 $ ./diff.py fileNumber1 fileNumber2 

如果您将文件保存在Git中,则可以使用diff-highlight脚本在不同版本之间进行区分,这些脚本将显示不同的行,并突出显示差异。

不幸的是,它只有当删除的行数与添加的行数相匹配时才有效 – 在存在行不匹配时存在存根代码,因此推测这可能在将来得到修复。

不是一个完整的答案,但是如果cmp -l的输出不够清晰,可以使用:

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