繁体   English   中英

如何使用 Python 的 difflib 生成类似于 Unix sdiff 命令的两个文件的并排比较?

[英]How to use Python's difflib to produce side-by-side comparison of two files similar to Unix sdiff command?

我正在使用 Python 2.6,我想创建一个简单的 GUI,其中有两个并排的文本窗格比较两个文本文件(file1.txt 和 file2.txt)。

我正在使用difflib ,但我不清楚如何生成类似于sdiff Unix 命令的结果。

例如,为了重现并排比较,我需要difflib返回两个变量file1_difffile2_diff

我也考虑过直接使用sdiff output 并解析它以分隔窗格,但结果并不像看起来那么容易......有什么提示吗?

这样的事情怎么样?

>>> a = ['cat', 'dog', 'horse']
>>> b = ['cat', 'horse', 'chicken']
>>> comparison = list(l for l in difflib.Differ().compare(a,b) if not l.startswith('?'))
>>> left = [l[2:] if l.startswith((' ', '-')) else '' for l in comparison]
>>> right = [l[2:] if l.startswith((' ', '+')) else '' for l in comparison]
>>> left
['cat', 'dog', 'horse', '']
>>> right
['cat', '', 'horse', 'chicken']

您可以使用difflib.Differ返回单个行序列,在描述该行的每行开头处带有一个标记。 标记会告诉您有关该行的以下信息:

标记 描述
'- ' 文件 1 独有的行
'+ ' 文件 2 独有的行
' ' 两个文件共有的行
'? ' 任一输入文件中都不存在该行

您可以使用此信息来决定如何显示数据。 例如,如果标记是 ,您将线放在左右小部件中。 如果它是+ ,您可以在左侧放置一个空行,在右侧放置实际行,以表明该行对于右侧的文本是唯一的。 同样, -表示该行在左侧是唯一的。

例如,您可以创建两个文本小部件t1t2 ,一个用于左侧,一个用于右侧。 您可以通过为每个文件创建一个行列表,然后将它们传递给差异的compare方法,然后迭代结果来比较两个文件。

t1 = tk.Text(...)
t2 = tk.Text(...)

f1 = open("file1.txt", "r").readlines()
f2 = open("file2.txt", "r").readlines()

differ = difflib.Differ()
for line in differ.compare(f1, f2):
    marker = line[0]
    if marker == " ":
        # line is same in both
        t1.insert("end", line[2:])
        t2.insert("end", line[2:])

    elif marker == "-":
        # line is only on the left
        t1.insert("end", line[2:])
        t2.insert("end", "\n")

    elif marker == "+":
        # line is only on the right
        t1.insert("end", "\n")
        t2.insert("end", line[2:])

上面的代码忽略带有标记的行? 因为这些是额外的行,试图引起人们对前一行不同字符的注意,并且实际上不是任何一个文件的一部分。 如果您愿意,您可以使用该信息来突出显示各个字符。

基于@Bryan Oakley 的回答,我写了一个简短的要点:

https://gist.github.com/jlumbroso/3ef433b4402b4f157728920a66cc15ed

使用并排差异方法(包括使用textwrap库生成这种并排排列的方法),您可以在两个行列表上调用:

print(better_diff(
    ["a", "c",      "a", "a", "a", "a",      "a", "a", "e"],
    ["a", "c", "b", "a", "a", "a", "a", "d", "a", "a"],
    width=20,
    as_string=True,
    left_title="  LEFT",
))

将产生:

  LEFT   | 
-------- | --------
a        | a
c        | c
         | b
a        | a
a        | a
a        | a
a        | a
         | d
a        | a
a        | a
e        | 

我试图用difflib.context_diff做文件差异:

diff = difflib.context_diff(fromlines, tolines, fromfile='file1.txt', tofile='file2.txt')
sys.stdout.writelines(diff)

在这种情况下,您的输出将是这样的:

*** file1.txt
--- file2.txt
***************
*** 1,6 ****
! aasdf
  qwer
  123
! poiu
! xzcv34
  xzcv
--- 1,6 ----
! asdf
  qwer
+ mnbv
  123
! cvnn
  xzcv

在这种情况下,您将能够轻松地分离每个文件差异,但我不确定您是否会对 context_diff 的输出感到满意。 您还没有提到您使用 difflib 的方式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM