经常需要比较两个文件(排序好的)中序列标号(每个标号占一行)的不同, 来寻找特有的或公有的标号。以往总是自己写程序处理, 偶然一次发现了diff(采用寻找最长公共子序列的算法,详见wiki)的强大功能,便尝试使用了一下, 未得要领,只好将其函数话来实现傻瓜操作。

首先举一个简单的例子来展示diff的使用
我们有如下两个文件:

1 2
1
2
3
4
5
6
7
3
4
5
10
7
8
9

使用diff命令diff 1 2输出结果如下:

1,2d0
< 1
< 2
6c4
< 6

10
7a6,7
8
9

a表示在第一个文件中需要加入的行,d表示在第一个文件中需要除去的航,c表示第一个文件中需要被替换的行。
我们可以把diff的结果输出到一个文件作为补丁,配合patch实现文件的修补。
另外,我们可以根据以上解释得出,以>开头的行为第二个文件独有,以<号开头的行为第一个文件独有, 由此引出我们下边的脚本比较。

这里提供了一个bash脚本和一个python程序来实现这个功能,方便操作。

#!/bin/bash
 
if test $# -ne 2; then
	echo 1&gt;&amp;2 "Usage $0 first second"
	exit 1
fi
 
FIRST=$1
SECOND=$2
tmp=`date +%Y-%m-%d `
#找到只存在于第一个里面的
diff $FIRST $SECOND | grep '<' | cut -d ' ' -f 2 | sort &gt;${FIRST}.${tmp}
#找到只存在于第一个里面的
diff $FIRST ${FIRST}.${tmp} | grep '<' | cut -d ' ' -f 2 | sort &gt;${FIRST}.${SECOND}.common
/bin/rm -f ${FIRST}.${tmp}
#!/usr/bin/env python
 
import sys
 
def main():
    if len(sys.argv) != 3:
        print 'Using python %s filename1 filename2' % sys.argv[]
        sys.exit()
    alist1 = [line for line in open(sys.argv[1])]
    sys.stdout.writelines([line for line in open(sys.argv[2]) \
            if line in alist1])
 
if __name__ == '__main__':
    main()

刚才还发现了有个diff3可以同时比较三个文件。