【问题标题】:Compare two files report difference in python比较两个文件报告python中的差异
【发布时间】:2018-08-06 03:12:19
【问题描述】:

我有 2 个名为“hosts”的文件(在不同的目录中)

我想用 python 比较它们,看看它们是否相同。如果它们不相同,我想在屏幕上打印差异。

到目前为止,我已经尝试过了

hosts0 = open(dst1 + "/hosts","r") 
hosts1 = open(dst2 + "/hosts","r")

lines1 = hosts0.readlines()

for i,lines2 in enumerate(hosts1):
    if lines2 != lines1[i]:
        print "line ", i, " in hosts1 is different \n"
        print lines2
    else:
        print "same"

但是当我运行它时,我得到了

File "./audit.py", line 34, in <module>
  if lines2 != lines1[i]:
IndexError: list index out of range

这意味着其中一个主机的行数比另一个多。 有没有更好的方法来比较 2 个文件并报告差异?

【问题讨论】:

  • 计算一个哈希值怎么样?作为快速找出它们是否不同的捷径
  • 使用 difflib 或只是控制台上的 diff 命令
  • @MrE 我已经看过那个了。它没有回答我的问题。我是python的初学者,这个问题一旦发现差异就会谈到散列和退出。我不想退出。我想打印出所有的差异。 (谢谢你)
  • @user2799617 我会研究 difflib 但 diff 命令是一个 linux 命令。 Python 不认识它..!!

标签: python file comparison


【解决方案1】:
import difflib

lines1 = '''
dog
cat
bird
buffalo
gophers
hound
horse
'''.strip().splitlines()

lines2 = '''
cat
dog
bird
buffalo
gopher
horse
mouse
'''.strip().splitlines()

# Changes:
# swapped positions of cat and dog
# changed gophers to gopher
# removed hound
# added mouse

for line in difflib.unified_diff(lines1, lines2, fromfile='file1', tofile='file2', lineterm=''):
    print line

输出以下内容:

--- file1
+++ file2
@@ -1,7 +1,7 @@
+cat
 dog
-cat
 bird
 buffalo
-gophers
-hound
+gopher
 horse
+mouse

此差异为您提供上下文 - 周围的行有助于清楚文件的不同之处。您可以在此处看到两次“猫”,因为它是从“狗”下方删除并添加到其上方的。

您可以使用 n=0 来删除上下文。

for line in difflib.unified_diff(lines1, lines2, fromfile='file1', tofile='file2', lineterm='', n=0):
    print line

输出这个:

--- file1
+++ file2
@@ -0,0 +1 @@
+cat
@@ -2 +2,0 @@
-cat
@@ -5,2 +5 @@
-gophers
-hound
+gopher
@@ -7,0 +7 @@
+mouse

但现在它充满了“@@”行,告诉您文件中已更改的位置。让我们删除多余的行以使其更具可读性。

for line in difflib.unified_diff(lines1, lines2, fromfile='file1', tofile='file2', lineterm='', n=0):
    for prefix in ('---', '+++', '@@'):
        if line.startswith(prefix):
            break
    else:
        print line

给我们这个输出:

+cat
-cat
-gophers
-hound
+gopher
+mouse

现在你想让它做什么? 如果您忽略所有已删除的行,那么您将看不到“猎犬”已被删除。 如果您对仅显示文件的添加内容感到满意,那么您可以这样做:

diff = difflib.unified_diff(lines1, lines2, fromfile='file1', tofile='file2', lineterm='', n=0)
lines = list(diff)[2:]
added = [line[1:] for line in lines if line[0] == '+']
removed = [line[1:] for line in lines if line[0] == '-']

print 'additions:'
for line in added:
    print line
print
print 'additions, ignoring position'
for line in added:
    if line not in removed:
        print line

输出:

additions:
cat
gopher
mouse

additions, ignoring position:
gopher
mouse

您现在可能已经知道有多种方法可以“打印出两个文件的差异”,因此如果您需要更多帮助,则需要非常具体。

【讨论】:

  • 就是这样。另外,有没有办法获得文件不同的行号?因为 for 循环中写着“for line in diff”,所以这个“line”是 diff 的行号。我想要原始文件的行号。
【解决方案2】:

difflib 库对此很有用,它位于标准库中。我喜欢统一的差异格式。

http://docs.python.org/2/library/difflib.html#difflib.unified_diff

import difflib
import sys

with open('/tmp/hosts0', 'r') as hosts0:
    with open('/tmp/hosts1', 'r') as hosts1:
        diff = difflib.unified_diff(
            hosts0.readlines(),
            hosts1.readlines(),
            fromfile='hosts0',
            tofile='hosts1',
        )
        for line in diff:
            sys.stdout.write(line)

输出:

--- hosts0
+++ hosts1
@@ -1,5 +1,4 @@
 one
 two
-dogs
 three

这是一个忽略某些行的狡猾版本。 可能有一些边缘情况不起作用,当然有更好的方法来做到这一点,但也许它对你的目的来说已经足够了。

import difflib
import sys

with open('/tmp/hosts0', 'r') as hosts0:
    with open('/tmp/hosts1', 'r') as hosts1:
        diff = difflib.unified_diff(
            hosts0.readlines(),
            hosts1.readlines(),
            fromfile='hosts0',
            tofile='hosts1',
            n=0,
        )
        for line in diff:
            for prefix in ('---', '+++', '@@'):
                if line.startswith(prefix):
                    break
            else:
                sys.stdout.write(line[1:])

【讨论】:

  • 谢谢。这和我想要的非常接近。但是有没有办法只展示狗而不展示其他东西?
  • 完美评价最好的答案现在只是最后一件事,您刚刚发布的最新方法将打印两个文件中的行。例如它会打印 Dogs Dosg 有没有办法只打印其中一个?而不是两者都有?
  • 我认为我不应该让它在打印时切断第一个字符。尝试从中删除[1:]。如果某些东西出现两次,可能是因为差异认为它被移动了——从一个地方删除并添加到另一个地方。也许您可以发布您的输入文件和预期的输出,因为我不太确定您想要实现什么。也许您更关心独特的行而不是它们在文件中的位置?
  • 好的。例如,在我的一个文件中,我在另一个“演员”中有“猫”。当我运行代码时,它完全符合我的要求,除了代码打印“Cats Cast”。我希望它只打印其中一个。
  • 我的回复不适合评论,所以我添加了一个新答案。
【解决方案3】:
hosts0 = open("C:path\\a.txt","r")
hosts1 = open("C:path\\b.txt","r")

lines1 = hosts0.readlines()

for i,lines2 in enumerate(hosts1):
    if lines2 != lines1[i]:
        print "line ", i, " in hosts1 is different \n"
        print lines2
    else:
        print "same"

上面的代码对我有用。你能指出你遇到了什么错误吗?

【讨论】:

  • 感谢您的回答,但我遇到了这个错误 File "./audit.py", line 34, in &lt;module&gt; if lines2 != lines1[i]: IndexError: list index out of range 这意味着我的一个文件的行数比另一个多。
【解决方案4】:

您可以添加条件语句。如果您的数组超出索引,则中断并打印文件的其余部分。

【讨论】:

    【解决方案5】:
    import difflib
    f=open('a.txt','r')  #open a file
    f1=open('b.txt','r') #open another file to compare
    str1=f.read()
    str2=f1.read()
    str1=str1.split()  #split the words in file by default through the spce
    str2=str2.split()
    d=difflib.Differ()     # compare and just print
    diff=list(d.compare(str2,str1))
    print '\n'.join(diff)
    

    【讨论】:

    • 简单的解决方案只需打开两个文件并拆分单词并将它们与不同的类进行比较。
    • 欢迎来到 Stack Overflow!请考虑编辑您的帖子,以添加更多关于您的代码的作用以及它为什么会解决问题的解释。一个大部分只包含代码的答案(即使它正在工作)通常不会帮助 OP 理解他们的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-03
    • 1970-01-01
    • 2014-06-08
    • 1970-01-01
    • 2021-06-30
    • 2016-12-24
    • 1970-01-01
    相关资源
    最近更新 更多