经常需要比较两个文件(排序好的)中序列标号(每个标号占一行)的不同, 来寻找特有的或公有的标号。以往总是自己写程序处理, 偶然一次发现了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>&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 >${FIRST}.${tmp} #找到只存在于第一个里面的 diff $FIRST ${FIRST}.${tmp} | grep '<' | cut -d ' ' -f 2 | sort >${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可以同时比较三个文件。