difflib中没有直接c
类似的代码来显示更改的行,就像您谈到的 Perl 的 sdiff 中那样。但是你可以很容易地做一个。在 difflib 的 delta 中,“更改的行”也有'- '
,但与实际删除的行相比,delta 中的下一行带有 标记,'? '
表示 delta 的前一个索引中的行是“更改”的,而不是删除的。这条线在 delta 中的另一个目的是它充当“指南”,以了解更改在哪里。
因此,如果 delta 中的一行被标记为'- '
,则根据 delta 的接下来几行,有四种不同的情况:
案例1:通过插入一些字符修改的行
- The good bad
+ The good the bad
? ++++
案例2:通过删除一些字符来修改行
- The good the bad
? ----
+ The good bad
情况 3:通过删除和插入和/或替换某些字符来修改行:
- The good the bad and ugly
? ^^ ----
+ The g00d bad and the ugly
? ^^ ++++
案例4:行被删除
- The good the bad and the ugly
+ Our ratio is less than 0.75!
如您所见,带有标记的行'? '
准确显示了在何处进行了何种类型的修改。
请注意,如果ratio()
正在比较的两行之间的值小于 0.75,则 difflib 认为删除了一行。这是我通过一些测试发现的值。
因此,要推断一条线已更改,您可以这样做。这将返回带有代码“c”标记的更改行和标记为“u”的未更改行的差异,就像在 Perl 的 sdiff 中一样:
def sdiffer(s1, s2):
differ = difflib.Differ()
diffs = list(differ.compare(s1, s2))
i = 0
sdiffs = []
length = len(diffs)
while i < length:
line = diffs[i][2:]
if diffs[i].startswith(' '):
sdiffs.append(('u', line))
elif diffs[i].startswith('+ '):
sdiffs.append(('+', line))
elif diffs[i].startswith('- '):
if i+1 < length and diffs[i+1].startswith('? '): # then diffs[i+2] starts with ('+ '), obviously
sdiffs.append(('c', line))
i += 3 if i + 3 < length and diffs[i + 3].startswith('? ') else 2
elif diffs[i+1].startswith('+ ') and i+2<length and diffs[i+2].startswith('? '):
sdiffs.append(('c', line))
i += 2
else:
sdiffs.append(('-', line))
i += 1
return sdiffs
希望能帮助到你。
PS:这是一个老问题,所以我不确定我的努力会得到多大的回报。:-(
我忍不住回答了这个问题,因为我最近一直在使用 difflib。