Python统一差异与两个“文件”中的行号

时间:2014-04-25 16:48:36

标签: python diff difflib

我正试图找出一种方法来创建统一的差异,其中行号仅显示N个上下文行。我无法使用difflib.unified_diff执行此操作。我需要在两个文件中显示更改。

我最接近的是在命令行上使用diff,如下所示:

/usr/bin/diff --unchanged-line-format=' %.2dn %L' --old-line-format="-%.2dn %L" --new-line-format="+%.2dn %L" file1.py file2.py

但是我只想显示N行的上下文,/usr/bin/diff似乎不支持自定义行格式的上下文(例如。-U2不是兼容--line-format“conflicting output style options”。

以下是我想要完成的示例(与上述差异相同的输出,但仅显示围绕更改的1行上下文):

+01: def renamed_function() -01: def original_function(): 02: +03: """ Neat stuff here """ 04: 21: +22: # Here's a new comment 23: 85: # Output the value of foo() +86: print "Foo is %s"%(foo()) -86: print foo() 87:

1 个答案:

答案 0 :(得分:0)

我能够找到一些非常接近我想做的事情。不过,它比普通差异要慢。以下是我的项目GitGate中的整个代码。

def unified_diff(to_file_path, from_file_path, context=1):

    """ Returns a list of differences between two files based
    on some context. This is probably over-complicated. """

    pat_diff = re.compile(r'@@ (.[0-9]+\,[0-9]+) (.[0-9]+,[0-9]+) @@')

    from_lines = []
    if os.path.exists(from_file_path):
        from_fh = open(from_file_path,'r')
        from_lines = from_fh.readlines()
        from_fh.close()

    to_lines = []
    if os.path.exists(to_file_path):
        to_fh = open(to_file_path,'r')
        to_lines = to_fh.readlines()
        to_fh.close()

    diff_lines = []

    lines = difflib.unified_diff(to_lines, from_lines, n=context)
    for line in lines:
        if line.startswith('--') or line.startswith('++'):
            continue

        m = pat_diff.match(line)
        if m:
            left = m.group(1)
            right = m.group(2)
            lstart = left.split(',')[0][1:]
            rstart = right.split(',')[0][1:]
            diff_lines.append("@@ %s %s @@\n"%(left, right))
            to_lnum = int(lstart)
            from_lnum = int(rstart)
            continue

        code = line[0]

        lnum = from_lnum
        if code == '-':
            lnum = to_lnum
        diff_lines.append("%s%.4d: %s"%(code, lnum, line[1:]))

        if code == '-':
            to_lnum += 1
        elif code == '+':
            from_lnum += 1
        else:
            to_lnum += 1
            from_lnum += 1

    return diff_lines