比较两个文本文件以找出差异并将它们输出到新的文本文件

Compare two text files to find differences and output them to a new text file

我正在尝试制作一个简单的数据比较文本文档。目标是让用户能够 select 一个文件,在这个文件中搜索某个参数,然后将这些参数打印到一个新的文本文档中,在将新文本文档中的那些参数与文本文档进行比较之后具有默认参数,然后在对它们进行比较后将差异打印到新的文本文档中。

我创建了一个简单的流程图来总结这一点:

这是我当前的代码。我正在使用差异库来比较这两个文件。

import difflib
from Tkinter import *
import tkSimpleDialog
import tkMessageBox
from tkFileDialog import askopenfilename

root = Tk()
w = Label(root, text ="Configuration Inspector")
w.pack()
tkMessageBox.showinfo("Welcome", "This is version 1.00 of Configuration Inspector")
filename = askopenfilename() # Logs File
filename2 = askopenfilename() # Default Configuration
compareFile = askopenfilename() # Comparison File
outputfilename = askopenfilename() # Out Serial Number Configuration from Logs

with open(filename, "rb") as f_input:
    start_token = tkSimpleDialog.askstring("Serial Number", "What is the serial number?")
    end_token = tkSimpleDialog.askstring("End Keyword", "What is the end keyword")
    reText = re.search("%s(.*?)%s" % (re.escape(start_token + ",SHOWALL"), re.escape(end_token)), f_input.read(), re.S)
    if reText:
        output = reText.group(1)
        fo = open(outputfilename, "wb")
        fo.write(output)
        fo.close()

        diff = difflib.ndiff(outputfilename, compareFile)
        print '\n'.join(list(diff))

    else:
        tkMessageBox.showinfo("Output", "Sorry that input was not found in the file")
        print "not found"

到目前为止的结果是程序正确地搜索了您 select 的文件,然后将它找到的参数打印到一个新的输出文本文件中。

尝试比较默认数据和输出文件这两个文件时出现问题。

当比较程序时会输出差异,但是,由于默认数据文件与输出文件有不同的行,它只会打印出不匹配的行而不是不匹配的参数。换句话说,我有这两个文件:

默认数据文本文件:

Data1 = 1
Data2 = 2
Data3 = 3
Data4 = 4
Data5 = 5
Data6 = 6

输出数据文本文件:

Data1 = 1
Data2 = 2
Data3 = 8
Data4 = 7

因此,由于 Data3 和 Data4 不匹配,difference.txt 文件(比较输出)应该显示这一点。例如:

Data3 = 8
Data4 = 7
Data5 = 5
Data6 = 6

但是它不匹配或比较这些行,它只是检查 space 中是否有一行。所以目前我的比较输出看起来像这样:

Data5 = 5
Data6 = 6

关于如何使比较显示文件参数之间的所有差异的任何想法?

如果您需要更多详细信息,请在评论中告诉我,我将编辑原文 post 以添加更多详细信息。

我不知道你想用 difflib.ndiff() 做什么。该函数接受两个字符串列表,但您传递给它的是文件名。

无论如何,这里有一个简短的演示,可以执行您想要的比较。它使用 dict 来加速比较过程。显然,我没有你的数据文件,所以这个程序使用字符串 .splitlines() 方法创建字符串列表。

逐行遍历默认数据列表。
如果输出中不存在该数据 dict,则打印默认行。
如果输出中存在具有该值的数据键 dict,则跳过该行。
如果找到密钥但输出 dict 中的值与默认值不同,则打印包含密钥和输出值的一行。

#Build default data list
defdata = '''
Data1 = 1
Data2 = 2
Data3 = 3
Data4 = 4
Data5 = 5
Data6 = 6
'''.splitlines()[1:]

#Build output data list
outdata = '''
Data1 = 1
Data2 = 2
Data3 = 8
Data4 = 7
'''.splitlines()[1:]

outdict = dict(line.split(' = ') for line in outdata)

for line in defdata:
    key, val = line.split(' = ')
    if key in outdict:
        outval = outdict[key]
        if outval != val:
            print '%s = %s' % (key, outval)
    else:
        print line

输出

Data3 = 8
Data4 = 7
Data5 = 5
Data6 = 6

以下是将文本文件读入行列表的方法。

with open(filename) as f:
    data = f.read().splitlines()

还有一个.readlines()方法,但在这里用处不大,因为它保留了每行末尾的\n换行符,而我们不希望那样。

请注意,如果文本文件中有任何空行,那么生成的列表将在该位置有一个空字符串 ''。此外,该代码不会删除每行上的任何前导或尾随空格或其他空格。但是,如果您需要这样做,Stack Overflow 上有成千上万的示例可以向您展示如何操作。


版本 2

这个新版本使用的方法略有不同。 它遍历在默认列表或输出列表中找到的所有键的排序列表。
如果仅在其中一个列表中找到某个键​​,则将相应的行添加到差异列表中。
如果在两个列表中都找到了一个键,但输出行与默认行不同,则将输出列表中的相应行添加到差异列表中。如果两行相同,则不会向差异列表中添加任何内容。

#Build default data list
defdata = '''
Data1 = 1
Data2 = 2
Data3 = 3
Data4 = 4
Data5 = 5
Data6 = 6
'''.splitlines()[1:]

#Build output data list
outdata = '''
Data1 = 1
Data2 = 2
Data3 = 8
Data4 = 7
Data8 = 8
'''.splitlines()[1:]

def make_dict(data):
    return dict((line.split(None, 1)[0], line) for line in data)

defdict = make_dict(defdata)
outdict = make_dict(outdata)

#Create a sorted list containing all the keys
allkeys = sorted(set(defdict) | set(outdict))
#print allkeys

difflines = []
for key in allkeys:
    indef = key in defdict
    inout = key in outdict
    if indef and not inout:
        difflines.append(defdict[key])
    elif inout and not indef:
        difflines.append(outdict[key])
    else:
        #key must be in both dicts
        defval = defdict[key]
        outval = outdict[key]
        if outval != defval:
            difflines.append(outval)

for line in difflines:
    print line

输出

Data3 = 8
Data4 = 7
Data5 = 5
Data6 = 6
Data8 = 8