示例1:difflib模块——两个字符串的差异对比

  通过使用difflib模块实现两个字符串的差异对比,然后以版本控制风格进行输出。

java文本比对差异 生成结果 文本差异对比 代码_python

java文本比对差异 生成结果 文本差异对比 代码_字符串_02

1 #!/usr/bin/evn python
 2 # --*-- coding: utf-8 --*--
 3 # Auther : Liu WeiDong
 4 import difflib
 5 
 6 text1 = '''test1:             #字符串1
 7 This module provides classes.
 8 including HTML and context.
 9 difflib document7.4
10 add string
11 '''
12 text1_lines = text1.splitlines()   #以行进行分隔
13 
14 text2 = '''test2:             #字符串2
15 This module provides classes.
16 including HTML and context.
17 difflib document7.5
18 '''
19 
20 text2_lines = text2.splitlines()
21 
22 d = difflib.Differ()         #创建Differ()对象
23 
24 diff = d.compare(text1_lines,text2_lines)       采用compare方法对字符串进行比较
25 print('\n'.join(list(diff)))

View Code

  可以将以上代码换行html格式,将如上脚本运行python diff.py > diff.html,在使用浏览器打开diff.html文件

java文本比对差异 生成结果 文本差异对比 代码_python

java文本比对差异 生成结果 文本差异对比 代码_字符串_02

1 #!/usr/bin/evn python
 2 # --*-- coding: utf-8 --*--
 3 # Auther : Liu WeiDong
 4 import difflib
 5 
 6 text1 = '''test1:             #字符串1
 7 This module provides classes.
 8 including HTML and context.
 9 difflib document7.4
10 add string
11 '''
12 text1_lines = text1.splitlines()   #以行进行分隔
13 
14 text2 = '''test2:             #字符串2
15 This module provides classes.
16 including HTML and context.
17 difflib document7.5
18 '''
19 
20 text2_lines = text2.splitlines()
21 
22 # d = difflib.Differ()         #创建Differ()对象
23 #
24 # diff = d.compare(text1_lines,text2_lines)       采用compare方法对字符串进行比较
25 # print('\n'.join(list(diff)))
26 
27 d = difflib.HtmlDiff()
28 print(d.make_file(text1_lines,text2_lines))

View Code

示例2:difflib模块——对比nginx配置文件

  当我们维护多个Nginx配置时,时常会对比不同版本配置文件的差异,使运维人员更加清晰的了解不同版本迭代后的更新项,实现的思路是读取两个需对比的配置文件,再以换行符作为分隔符,调用difflib.HtmlDiff()生成HTML格式的差异文档。

java文本比对差异 生成结果 文本差异对比 代码_python

java文本比对差异 生成结果 文本差异对比 代码_字符串_02

1 #!/usr/bin/evn python
 2 # --*-- coding: utf-8 --*--
 3 # Auther : Liu WeiDong
 4 
 5 
 6 import difflib
 7 import sys
 8 
 9 #首先判断脚本是否传了正确参数
10 
11 try:
12     textfile1 = sys.argv[1]
13     textfile2 = sys.argv[2]
14 except Exception as e:
15     print("Error" + str(e))
16     print("Usage: simple3.py filename1 filename2")
17     sys.exit()
18 
19 #定义一个读取文件的函数,以换行符进行分隔
20 def readfile(filename):
21     try:
22         with open(filename,'rb') as fin:
23             text = fin.read().splitlines()
24             return text
25     except IOError as error:
26         print("Read file Error:" + str(error))
27         sys.exit()
28 
29 text1_lines = readfile(textfile1)
30 text2_lines = readfile(textfile2)
31 
32 d = difflib.HtmlDiff()
33 print(d.make_file(text1_lines,text2_lines))

View Code

    运行代码: 

# python simple3.py nginx.v1.conf nginx.v2.conf > diff.html

示例三:filecmp模块——文件与目录差异对比

  模块常用方法说明:fileemp提供了三个操作方法,分别为cmp(单文件对比)、cmpfile(多文件对比)、dircmp(目录对比),下面逐一进行介绍:

  •  单文件对比,采用filecmp.cmp (f1,f2[,shallow])方法,比较文件名为f1和f2的文件,相同返回True,不相同返回False,shallow默认为True。
  •  多文件对比,采用filecmp.cmpfiles(dir1,dir2,common[,shallow])方法,对比dir1与dir2目录给定的文件清单。该方法返回文件名的三个列表,分别为匹配,不匹配,错误。匹配为包含匹配的文件的列表,不匹配反之,错误列表包括了目录不存在的文件、不具备读权限或其他原因导致的不能比较的文件清单。
  • 目录对比,采用filecmp.dircmp(a,b[,ignore[,hide]])类创建一个目录比较对象,其中a和b是参加比较的目录名。ignore代表文件名忽略的列表,并默认为['RCS','CVS','tags'];hide代表隐藏的列表,默认为[os.curdir(当前目录),os.pardir(上一层目录)],dircmp类可以获得目录比较的详细信息,如只有在a目录中包括的文件、a与b都存在的子目录、匹配的文件等,同时支持递归。

java文本比对差异 生成结果 文本差异对比 代码_ide_07

java文本比对差异 生成结果 文本差异对比 代码_字符串_08

示例四:校验源与备份目录差异

  有时候我们无法确认备份目录与源目录文件是否一致,包括源目录中的新文件或目录、更新文件或目录有无成功同步,定期进行校验,没有成功则希望有针对性地进行补备份。

  如下示例使用了filecmp模块的left_only、diff_files方法递归获取源目录的更新项,在通过shutil.copyfile、os.makedirs方法对更新项进行复制,最终保持一致状态。代码如下:

java文本比对差异 生成结果 文本差异对比 代码_python

java文本比对差异 生成结果 文本差异对比 代码_字符串_02

1 #!/usr/bin/evn python
 2 # --*-- coding: utf-8 --*--
 3 # Auther : Liu WeiDong
 4 
 5 import os,sys
 6 import filecmp
 7 import re
 8 import shutil
 9 
10 holderlist = []
11 
12 # 定义一个函数,判断两个目录差异
13 def compareme(dir1,dir2):
14     dircomp = filecmp.dircmp(dir1,dir2)
15     only_in_leftdir = dircomp.left_only    #返回一个只在dir1中的文件或目录列表
16     diff_in_leftdir = dircomp.diff_files   #显示返回两个目录中相同文件名,内容不同
17     #dirpath = os.path.abspath(dir1)       # 定义源文件的绝对路径
18 
19     #将更新的文件名或目录追加到holderlist
20     for i in only_in_leftdir:
21         holderlist.append(os.path.abspath(os.path.join(dir1,i)))
22 
23     for i in diff_in_leftdir:
24         holderlist.append(os.path.abspath(os.path.join(dir1,i)))
25 
26     #判断是否存在相同子目录,以便递归
27     if len(dircomp.common_dirs) > 0:
28         for i in dircomp.common_dirs:
29             compareme(os.path.abspath(os.path.join(dir1,i)),os.path.abspath(os.path.join(dir2,i)))
30         return holderlist
31 
32 def main():
33     if len(sys.argv) > 2:   #判断脚本参数个数是否大于2
34         dir1 = sys.argv[1]
35         dir2 = sys.argv[2]
36     else:
37         print("Usage: ",sys.argv[0]," datadir backupdir")
38         sys.exit()
39 
40     #调用compareme函数,对传入的两个目录进行对比
41     different_file = compareme(dir1,dir2)
42     dir1 = os.path.abspath(dir1)
43 
44     if not dir2.endswith("/"):
45         dir2 = dir2 + '/'
46         dir2 = os.path.abspath(dir2)
47         destination_files = []
48         creatdir_bool = False
49 
50     for item in different_file:  #遍历返回的差异文件或目录列表
51         destination_dir = re.sub(dir1,dir2,item)  #将源目录差异路径清单对应替换成备份目录
52         destination_files.append(destination_dir) # 备份目录内容更新到定义的destination_files列表中
53         if os.path.isdir(item):       # 如果差异路径为目录且不存在,则在备份目录中创建
54             if not os.path.exists(destination_dir):
55                 os.makedirs(destination_dir)
56                 creatdir_bool = True
57 
58     if creatdir_bool:   #重新调用compareme函数,重新遍历创建目录的内容
59         destination_files = []
60         different_file = []
61         different_file = compareme(dir1,dir2)
62         for item in different_file:
63             destination_dir = re.sub(dir1,dir2,item)
64             destination_files.append(destination_dir)
65 
66     print("update item:")
67     print(destination_files)
68     copy_pair = zip(different_file,destination_files)
69     for item in copy_pair:
70         if os.path.isfile(item[0]):
71             shutil.copyfile(item[0],item[1])
72 
73 if __name__ == '__main__':
74     main()

View Code

 

不积跬步,无以至千里;不积小流,无以成江海。