如何使用difflib.ndiff忽略行?

时间:2010-01-08 20:34:57

标签: python

根据文档,您可以提供一个linejunk函数来忽略certian行。但是,我无法让它发挥作用。以下是一些供讨论的示例代码:

from re import search
from difflib import ndiff 
t1 = 'one 1\ntwo 2\nthree 3'
t2 = 'one 1\ntwo 29\nthree 3'
diff = ndiff(t1.splitlines(), t2.splitlines(), lambda x: search('2', x))

我的意图是忽略第二行,diff将是一个没有任何差异的生成器。

感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

我最近遇到了同样的问题。

这是我发现的:

比照http://bugs.python.org/issue14332

  

* junk参数的主要目的是加快匹配   找到差异,而不是掩盖差异。

c.f。 http://hg.python.org/cpython/rev/0a69b1e8b7fe/

补丁提供了对difflib docs中“垃圾”和“忽略”概念的更好解释

  

这些垃圾过滤功能可加快匹配以找到差异   并且不要忽略任何不同的行或字符。

答案 1 :(得分:0)

你的例子有一个问题:ndiff的前两个参数应该都是一个字符串列表;你有一个字符串,它被视为一个字符列表。见the docs。使用例如t1 = 'one 1\ntwo 2\nthree 3'.splitlines()

但是,如下例所示,difflib.ndiff不会为所有行调用linejunk函数。这是长期存在的行为 - 使用Python 2.2到2.6验证,以及3.1。

示例脚本:

from difflib import ndiff
t1 = 'one 1\ntwo 2\nthree 3'.splitlines()
t2 = 'one 1\ntwo 29\nthree 3'.splitlines()
def lj(line):
    rval = '2' in line
    print("lj: line=%r, rval=%s" % (line, rval))
    return rval
d = list(ndiff(t1, t2    )); print("%d %r\n" %  (1, d))
d = list(ndiff(t1, t2, lj)); print("%d %r\n" %  (2, d))
d = list(ndiff(t2, t1, lj)); print("%d %r\n" %  (3, d))

使用Python 2.6运行的输出:

1 ['  one 1', '- two 2', '+ two 29', '?      +\n', '  three 3']

lj: line='one 1', rval=False
lj: line='two 29', rval=True
lj: line='three 3', rval=False
2 ['  one 1', '- two 2', '+ two 29', '?      +\n', '  three 3']

lj: line='one 1', rval=False
lj: line='two 2', rval=True
lj: line='three 3', rval=False
3 ['  one 1', '- two 29', '?      -\n', '+ two 2', '  three 3']

您可能希望将此报告为错误。但请注意,文档没有明确说明“垃圾”行的含义是什么。你期待什么输出?

进一步的困惑:将这些行添加到脚本中:

t3 = 'one 1\n   \ntwo 2\n'.splitlines()
t4 = 'one 1\n\n#\n\ntwo 2\n'.splitlines()
d = list(ndiff(t3, t4      )); print("%d %r\n" %  (4, d))
d = list(ndiff(t4, t3      )); print("%d %r\n" %  (5, d))
d = list(ndiff(t3, t4, None)); print("%d %r\n" %  (6, d))
d = list(ndiff(t4, t3, None)); print("%d %r\n" %  (7, d))

生成此输出:

4 ['  one 1', '-    ', '+ ', '+ #', '+ ', '  two 2']

5 ['  one 1', '+    ', '- ', '- #', '- ', '  two 2']

6 ['  one 1', '-    ', '+ ', '+ #', '+ ', '  two 2']

7 ['  one 1', '+    ', '- ', '- #', '- ', '  two 2']

换句话说,使用默认linejunk函数的结果与不使用linejunk函数的结果相同,在包含不同“垃圾”行的情况下(除了初始哈希之外的空格)。

也许如果你能告诉我们你想要达到的目标,我们或许可以提出另一种方法。

进一步信息后修改

如果你的意图是一般性地忽略所有包含'2'的行,意味着假装它们不存在用于ndiff目的,你所要做的就是把假装变为现实:

t1f = [line for line in t1 if '2' not in line]
t2f = [line for line in t2 if '2' not in line]
diff = ndiff(t1f, t2f)
相关问题