使用SequenceMatcher生成内容差异(Python)

3 投票
1 回答
1717 浏览
提问于 2025-04-15 22:20

我想在Python中生成两个文本版本之间的差异(更具体来说,是Markdown格式的文章)。

我希望这个差异的格式能和Github上显示的类似。

我查看了difflib,发现它能满足我的需求。不过,Differ这个类太高级了;我需要解析差异行才能生成带有内联差异的HTML。Differ类使用SequenceMatcher类来生成差异。但看起来SequenceMatcher的功能比较底层。我甚至还没弄明白怎么进行逐行比较(我承认我没有花太多时间去尝试)。

有没有人知道使用SequenceMatcher类的资源(除了difflib的文档)?

1 个回答

9

SequenceMatcher其实并没有那么复杂。对你来说,最有趣的方法是 get_grouped_opcodes。这个方法会返回一个生成器,它会生成一些包含更改描述的列表。

我用一个来自GitHub上的随机提交的例子来解释。假设你在旧文件和新文件“tabs_events.js”上运行 SequenceMatcher(None, a, b).get_grouped_opcodes()。这个生成器会生成两个组,这些组在GitHub上用“...”来表示。基本上,这就是一组更改。在每个组里,你会看到详细的更改列表,这些更改以元组的形式存储。对于第一个组,它返回两个更改,格式如下(第一个项是更改类型,接下来的两个数字表示要删除的行范围,最后是要添加的行范围):

('replace', 24, 29, 24, 29)
('insert', 33, 33, 33, 35)

第一个更改告诉你要用新文件的第24-28行替换旧文件的第24-28行。第二个更改则告诉你要在旧文件的第33行插入新文件的第33-34行。我想你应该能明白 'delete' 是做什么的,而 'equal' 是那些在GitHub上没有高亮显示的行。

如果你不介意看源代码,可以看看 difflib.unified_diff() 的实现。它其实很简单,可以生成你想要的纯文本格式。

撰写回答