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

Python 比较两个文本文件以找出差异并将其输出到新的文本文件,python,io,compare,diff,Python,Io,Compare,Diff,我正在尝试编写一个简单的数据比较文本文档。目标是让用户能够选择一个文件,在该文件中搜索某个参数,然后将这些参数打印到新的文本文档中,将新文本文档中的这些参数与具有默认参数的文本文档进行比较后,然后将这些参数进行比较后,将差异打印到新文本文档中 我创建了一个简单的流程图来总结这一点: 这是我当前的代码。我正在使用diff库来比较这两个文件 import difflib from Tkinter import * import tkSimpleDialog import tkMessageBox

我正在尝试编写一个简单的数据比较文本文档。目标是让用户能够选择一个文件,在该文件中搜索某个参数,然后将这些参数打印到新的文本文档中,将新文本文档中的这些参数与具有默认参数的文本文档进行比较后,然后将这些参数进行比较后,将差异打印到新文本文档中

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

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

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"
到目前为止,结果是程序正确地搜索了您选择要搜索的文件,然后将找到的参数打印到新的输出文本文件中

在尝试比较两个文件(默认数据和输出文件)时会出现问题

然而,当比较时,程序将输出差异,因为默认数据文件与输出文件具有不同的行,所以它将只打印不匹配的行,而不是不匹配的参数。换句话说,假设我有两个文件:

默认数据文本文件:

Data1 = 1
Data2 = 2
Data3 = 3
Data4 = 4
Data5 = 5
Data6 = 6
Data1 = 1
Data2 = 2
Data3 = 8
Data4 = 7
输出数据文本文件:

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
但是,它不匹配或比较行,它只是检查该空间中是否有行。因此,当前我的比较输出如下所示:

Data5 = 5
Data6 = 6
关于如何使比较显示文件参数之间的所有差异,有什么想法吗


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

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

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

它逐行遍历默认数据列表。
如果输出中不存在该数据,则打印默认行。
如果输出中存在具有该值的数据键,则跳过该行。
如果找到了键,但输出
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
Data3 = 8
Data4 = 7
Data5 = 5
Data6 = 6
Data8 = 8

下面介绍如何将文本文件读入行列表

with open(filename) as f:
    data = f.read().splitlines()
还有一个
.readlines()
方法,但它在这里不是很有用,因为它在每行末尾保留了
\n
换行符,我们不希望这样

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


版本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
Data3 = 8
Data4 = 7
Data5 = 5
Data6 = 6
Data8 = 8

你试过做些什么来比较它们吗?我不确定问题是什么。所以问题是默认数据文件与输出文件比较。但是,由于Data3和Data4的参数在两个文件中都不同,因此没有显示它们是不同的。它忽略它们,只报告/打印它没有的行。看起来你有一个ini文件。您是否尝试过使用configparser之类的工具加载文件,然后从中进行比较?看起来您想要打印其中一个文件中的所有行,而不是另一个文件中的所有行。如果这是正确的,那么很容易做到,您不需要difflib。如果你想做更复杂的事情,请具体说明。你想做的事情和我建议的有什么不同吗?是否曾经出现过打印两个文件中都出现的行的情况?是否有过这样的情况,即您无法打印其中一个文件中的一行而不是另一个文件中的一行?很抱歉,我对python非常陌生,我想我可以将txt文档中的字符串传递给difflib,至于您的代码,这是朝着正确方向迈出的一步。我试图让它比较数据文件而不是列表。splitlines()可以打开文本文档吗?例如:Default=askopenfilename(),然后尝试类似defdata=Default.splitlines()[1:]?如果输出数据列表中有一行
Data8=8
,该怎么办?那不应该也印出来吗?在我看来,OP想要的是对称的差异,可以说,是dicts的差异。另外,如果在输出数据中以两种不同的方式配置了相同的参数,该怎么办。这不应该被标记吗?@saulspatz是的,因为Data8=8不是应该打印的默认值。@JeanP:对不起,如果我的当前代码在输出数据列表中,但不在默认数据列表中,我的当前代码将不会打印
Data8=8
。我没有意识到你想要那个,我只是从你的示例数据中得到的。@JeanP:我稍后会解决这个问题-我现在做不到,因为我的时区已经很晚了。但我现在将添加一些代码来演示如何将文本文件读入行列表。