Как использовать difflib Python для сравнения двух файлов, аналогичных команде Unix sdiff?

Я использую Python 2.6 и хочу создать простой графический интерфейс с двумя параллельными текстовыми панелями, сравнивающими два текстовых файла (file1.txt & file2.txt).

Я использую difflib, но мне не ясно, как получить результат, похожий на команду Unix sdiff.

Чтобы воспроизвести параллельное сравнение, мне нужен difflib, чтобы вернуть две переменные file1_diff а также file2_diff, например.

Я также решил использовать вывод sdiff напрямую и проанализировать его для разделения панелей, но оказалось, что это не так просто, как кажется... Есть подсказки?

4 ответа

Основываясь на ответе @Bryan Oakley, я написал краткую суть:

https://gist.github.com/jlumbroso/3ef433b4402b4f157728920a66cc15ed

с помощью метода параллельного сравнения (включая метод создания этого параллельного расположения с использованием textwrapбиблиотеку), которую вы можете вызывать в двух списках строк:

      print(better_diff(
    ["a", "c",      "a", "a", "a", "a",      "a", "a", "e"],
    ["a", "c", "b", "a", "a", "a", "a", "d", "a", "a"],
    width=20,
    as_string=True,
    left_title="  LEFT",
))

будет производить:

        LEFT   | 
-------- | --------
a        | a
c        | c
         | b
a        | a
a        | a
a        | a
a        | a
         | d
a        | a
a        | a
e        | 

Вы можете использовать difflib.Differ для возврата одной последовательности строк с маркером в начале каждой строки, который описывает строку. Маркеры сообщают вам следующую информацию о линии:

Вы можете использовать эту информацию, чтобы решить, как отображать данные. Например, если маркер , ставишь строчку и в левый и в правый виджеты. Если это + , вы можете поместить пустую строку слева и фактическую строку справа, показывая, что строка уникальна для текста справа. Так же, - означает, что линия уникальна слева.

Например, вы можете создать два текстовых виджета t1а также t2, один для левого и один для правого. Вы можете сравнить два файла, создав список строк для каждого, а затем передав их в compareметод разницы, а затем повторение результатов.

      t1 = tk.Text(...)
t2 = tk.Text(...)

f1 = open("file1.txt", "r").readlines()
f2 = open("file2.txt", "r").readlines()

differ = difflib.Differ()
for line in differ.compare(f1, f2):
    marker = line[0]
    if marker == " ":
        # line is same in both
        t1.insert("end", line[2:])
        t2.insert("end", line[2:])

    elif marker == "-":
        # line is only on the left
        t1.insert("end", line[2:])
        t2.insert("end", "\n")

    elif marker == "+":
        # line is only on the right
        t1.insert("end", "\n")
        t2.insert("end", line[2:])

Приведенный выше код игнорирует строки с маркером ? поскольку это дополнительные строки, которые пытаются привлечь внимание к другим символам в предыдущей строке и на самом деле не являются частью ни одного из файлов. Вы можете использовать эту информацию, чтобы выделить отдельные символы, если хотите.

Как насчет этого?

>>> a = ['cat', 'dog', 'horse']
>>> b = ['cat', 'horse', 'chicken']
>>> comparison = list(l for l in difflib.Differ().compare(a,b) if not l.startswith('?'))
>>> left = [l[2:] if l.startswith((' ', '-')) else '' for l in comparison]
>>> right = [l[2:] if l.startswith((' ', '+')) else '' for l in comparison]
>>> left
['cat', 'dog', 'horse', '']
>>> right
['cat', '', 'horse', 'chicken']

Я пытался сделать файлы diff с difflib.context_diff:

diff = difflib.context_diff(fromlines, tolines, fromfile='file1.txt', tofile='file2.txt')
sys.stdout.writelines(diff)

В этом случае ваш вывод будет примерно таким:

*** file1.txt
--- file2.txt
***************
*** 1,6 ****
! aasdf
  qwer
  123
! poiu
! xzcv34
  xzcv
--- 1,6 ----
! asdf
  qwer
+ mnbv
  123
! cvnn
  xzcv

В этом случае вы сможете легко разделить каждый файл diff, но я не уверен, что вы будете удовлетворены выводом context_diff. Вы не упомянули, каким образом вы используете difflib.

Другие вопросы по тегам