Генерация различий в содержимом с использованием SequenceMatcher (Python) - PullRequest
2 голосов
/ 04 мая 2010

Я хочу создать разницу между ревизиями текста (точнее, статей в формате Markdown) в Python.

Я хочу отформатировать этот дифференциал способом, подобным тому, что делает Github .

Я посмотрел на difflib и обнаружил, что он делает то, что я хочу. Однако класс Differ слишком высокого уровня; Мне нужно было бы проанализировать строки diff для генерации HTML с помощью встроенных diff. Класс Differ использует класс SequenceMatcher для генерации своих различий. Но, глядя на SequenceMatcher, это очень низкий уровень по сравнению. Я даже не понял, как проводить построчное сравнение (я признаю, что не потратил много времени на эксперименты).

Кто-нибудь знает какие-либо ресурсы для использования класса SequenceMatcher (кроме документация difflib )?

1 Ответ

8 голосов
/ 05 мая 2010

SequenceMatcher на самом деле не настолько низкоуровневый.Самый интересный способ для вас это get_grouped_opcodes.Он вернет генератор, который генерирует списки с описаниями изменений.

Я объясню это на примере случайного коммита на GitHub .Допустим, вы запускаете SequenceMatcher(None, a, b).get_grouped_opcodes() для старого и нового файла "tabs_events.js".Генератор сгенерирует две группы, которые представлены этими строками "..." в GitHub.Это в основном группа изменений.В каждой из групп у вас есть список подробных изменений, хранящихся в виде кортежей.Для первой группы она возвращает два изменения, которые выглядят следующим образом (первый элемент является типом изменения, следующие два числа представляют диапазон строк, которые должны быть удалены, а затем диапазон строк, который необходимо добавить):

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

Первый говорит вам заменить строки 24-28 (начиная с 0) из старого файла на строки 24-28 из нового файла.Второй говорит вам вставить строки 33-34 из нового файла в строку 33 в старом файле.Я думаю, что ясно, что 'delete' делает и 'equal' - это те строки, которые не выделены в GitHub.

Если вы не возражаете против чтения исходного кода, посмотрите на реализацию difflib.unified_diff().Это довольно просто и генерирует текстовый эквивалент того, что вы хотите.

...