我正在阅读Python difllib的文档。根据每个文档,Differ delta给出一个序列
Code Meaning
'- ' line unique to sequence 1
'+ ' line unique to sequence 2
' ' line common to both sequences
'? ' line not present in either input sequence
但是“改变”操作怎么样?如何获得类似于Perl的sdiff中的结果的“c”指令?
答案 0 :(得分:1)
显示此脚本。
sdiff.py @ hungrysnake.net
http://hungrysnake.net/doc/software__sdiff_py.html
Perl的sdiff(Algorithm :: Diff)不要考虑"匹配率", 但是python的sdiff.py想一想。 =)
我有2个文本文件。
$ cat text1.txt
aaaaaa
bbbbbb
cccccc
dddddd
eeeeee
ffffff
$ cat text2.txt
aaaaaa
bbbbbb
xxxxxxx
ccccccy
zzzzzzz
eeeeee
ffffff
我通过sdiff命令或Perl的sdiff(Algorithm :: Diff)并排运行。
$ sdiff text1.txt text2.txt
aaaaaa aaaaaa
bbbbbb bbbbbb
cccccc | xxxxxxx
dddddd | ccccccy
> zzzzzzz
eeeeee eeeeee
ffffff ffffff
Sdiff不考虑"匹配率" =(
我是通过sdiff.py获得的。
$ sdiff.py text1.txt text2.txt
--- text1.txt (utf-8)
+++ text2.txt (utf-8)
1|aaaaaa 1|aaaaaa
2|bbbbbb 2|bbbbbb
| > 3|xxxxxxx
3|cccccc | 4|ccccccy
4|dddddd < |
| > 5|zzzzzzz
5|eeeeee 6|eeeeee
6|ffffff 7|ffffff
[ ] | +
[ <- ] 3|cccccc
[ -> ] 4|ccccccy
Sdiff.py考虑&#34;匹配率&#34; =)
我想要sdiff.py的结果。不是吗?
答案 1 :(得分:1)
在difflib中没有直接的c
代码来显示更改的行,就像你在谈到的Perl的sdiff中那样。但你可以轻松制作一个。在difflib的delta中,&#34;更改了行&#34;也有'- '
,但与实际删除的行相比,增量中的下一行标有'? '
,表示前一个增量索引中的行是&#34;已更改&# 34;,未删除。这条线在三角洲的另一个目的是它作为&#39;指南&#39;至于变化在哪里。
因此,如果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会认为删除了一条线。这是我通过一些测试发现的值。
因此,要将行推断为已更改,您可以执行此操作。这将返回带有代码&#39; c&#39;标记的更改行的差异,以及标记为&#39; u&#39;的未更改行,就像在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
希望它有所帮助。
P.S。 :这是一个老问题,所以我不确定我的努力会有多好。 :-(
我无法回答这个问题,因为我最近一直在和difflib一起工作。
答案 2 :(得分:0)
我几乎不知道Perl的“更改”操作是什么。如果它类似于PHP DIFF输出,我用这段代码解决了我的问题:
def sdiffer(s1, s2):
differ = difflib.Differ()
diffs = list(differ.compare(s1, s2))
i = 0
sdiffs = []
length = len(diffs)
sequence = 0
while i < length:
line = diffs[i][2:]
if diffs[i].startswith(' '):
sequence +=1
sdiffs.append((sequence,'u', line))
elif diffs[i].startswith('+ '):
sequence +=1
sdiffs.append((sequence,'+', line))
elif diffs[i].startswith('- '):
sequence +=1
sdiffs.append((sequence,'-',diffs[i][2:]))
if i+1 < length and diffs[i+1].startswith('? '):
if diffs[i+3].startswith('?') and i+3 < length : # case 2
sequence +=1
sdiffs.append((sequence,'+',diffs[i+2][2:]))
i+=3
elif diffs[i+2].startswith('?') and i+2 < length: # case 3
sequence +=1
sdiffs.append((sequence,'+',diffs[i+2][2:]))
i+=2
elif diffs[i+1].startswith('+ ') and i+2<length and diffs[i+2].startswith('? '): # case 1
sequence +=1
sdiffs.append((sequence,'+', diffs[i+1][2:]))
i += 2
else: # the line is deleted and inserted new line # case 4
sequence +=1
sdiffs.append((sequence,'+', diffs[i+1][2:]))
i+=1
i += 1
return sdiffs
感谢@Sнаđошƒаӽ代码。