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