7.1.8 文件的比较

Python提供了模块difflib,现实对序列、文件的比较。如果要比较两个文件,列出两个文件的异同,可以使用difflib模块的SequenceMatcher类实现。其中的方法get_opcodes()可以返回两个序列的比较结果。调用方法get_opcodes()前,需要先生成1个SequenceMatcher对象。SequenceMatcher()的声明如下所示。


class SequenceMatcher( [isjunk[, a[, b]]])

其中,isjunk表示比较过程中是否匹配指定的字符或字符串,a、b表示待比较的两个序列。生成序列比较对象后,调用该对象的get_opcodes()方法,将返回1个元组(tag,i1,i2,j1,j2)。tag表示序列分片的比较结果。i1、i2表示序列a的索引,j1、j2表示序列b的索引。表7-5列出了get_opcodes()返回元组(tag,i1,i2,j1,j2)的含义。

表7-5 get_opcodes()返回元组(tag,i1,i2,j1,j2)的含义

注意 SequenceMatcher(None,a,b)创建序列比较对象,将以a作为参考标准进行比较;SequenceMatcher(None,b,a)创建序列比较对象,则以b作为参考标准进行比较。

例如,有两个文本文件hello.txt与hi.txt,现要获得两个文件的异同。hello.txt文件的内容如下所示。


hello world

hi.txt文件的内容如下所示。


hi hello

下面【例7-5】这段代码以hello.txt文件为参照,实现了两个文件的比较,并返回比较结果。

【例7-5.py】


01     import difflib                    # 导入difflib模块
02
03     f1 = open("hello.txt", "r")
04     f2 = open("hi.txt", "r")
05     src = f1.read()
06     dst = f2.read()
07     print (src)
08     print (dst)
09     s = difflib.SequenceMatcher( lambda x: x == "", src, dst)
10     for tag, i1, i2, j1, j2 in s.get_opcodes():
11         print ("%s src[%d:%d]=%s dst[%d:%d]=%s" % \
12         (tag, i1, i2, src[i1:i2], j1, j2, dst[j1:j2]))

【代码说明】

·第9行代码生成1个序列匹配的对象s,其中lambda x:x==""表示忽略hi.txt中的换行符。如果hi.txt中有多余的换行,并不会作为不同点返回。

·第10行代码调用方法get_opcodes()获取文件hello.txt与hi.txt的比较结果。

·第11、12行代码输出比较结果。如果hello.txt与hi.txt的内容需要完全一致,在hello.txt的开始处插入字符串“hi”,并删除hello.txt中的字符串“world”,hello.txt的内容分片[0:5]与hi.txt的内容分片[3:8]相同。比较结果如下所示。


insert src[0:0]= dst[0:3]=hi
equal src[0:5]=hello dst[3:8]=hello
delete src[5:13]= world dst[8:8]=