Отображение номеров строк в двух файлах diff с использованием emacs / python / winmerge - PullRequest
4 голосов
/ 01 декабря 2011

Рассмотрим следующие два файла, которые немного отличаются:

foo (старая версия):

<Line 1> a
<Line 2> b
<Line 3> c
<Line 4> d

foo (новая версия):

<Line 1> a
<Line 2> e
<Line 3> b
<Line 4> c
<Line 5> f
<Line 6> d

Как видите, символы e и f введены в новый файл.

У меня есть набор номеров строк, соответствующих старому файлу… скажем, 1, 3 и 4 (соответствует буквам a, c и d).

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

ЭГ., Результат будет:

Old file line numbers (1,3,4) ===> New File line numbers (1,4,6)

К сожалению, в моем распоряжении только emacs (с рабочим ediff), Python и winmerge.

Ответы [ 2 ]

3 голосов
/ 01 декабря 2011

Вы можете сделать все это в Emacs:

(defun get-joint-index (file-a index file-b)
  (let ((table (make-hash-table :test #'equal)))
    (flet ((line () (buffer-substring-no-properties
                     (point-at-bol) (point-at-eol))))
      (with-temp-buffer (insert-file file-b)
        (loop for i from 1 do (puthash (line) i table)
              while (zerop (forward-line))))
      (with-temp-buffer (insert-file file-a)
        (loop for i in index do (goto-line i)
              collect (gethash (line) table))))))

Для запуска,

M -: (get-joint-index "/tmp/old" '(1 3 4) "/tmp/new")

-> (1 4 6)

2 голосов
/ 01 декабря 2011

Вам нужен алгоритм поиска строк , где у вас есть несколько шаблонов (строк из старой версии foo), которые вы хотите искать в тексте (новая версия foo). Алгоритм Рабина-Карпа является одним из таких алгоритмов для такого рода задач. Я адаптировал это к вашей проблеме:

def linematcher(haystack, needles, lineNumbers):
    f = open(needles)
    needles = [line.strip() for n, line in enumerate(f, 1) if n in lineNumbers]
    f.close()

    hsubs = set(hash(s) for s in needles)
    for n, lineWithNewline in enumerate(open(haystack), 1):
        line = lineWithNewline.strip()
        hs = hash(line)
        if hs in hsubs and line in needles:
            print "{0} ===> {1}".format(lineNumbers[needles.index(line)], n)

Если предположить, что ваши два файла называются old_foo.txt и new_foo.txt, то вы бы назвали эту функцию следующим образом:

linematcher('new_foo.txt', 'old_foo.txt', [1, 3, 4])

Когда я попробовал ваши данные, он напечатал:

1 ===> 1
3 ===> 4
4 ===> 6
...