vimdiff: принудительное построчное сравнение (игнорировать предположительно отсутствующие / дополнительные строки)

Как заставить vimdiff всегда сравнивать два файла построчно, не определяя добавленные или удаленные строки?

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

Ниже приведен небольшой пример с двумя файлами, содержащими значения двух переменных по три раза каждый. Vimdiff ошибочно сопоставляет file1 / line1 с file2 / line3 и считает, что некоторые строки вокруг него были добавлены или удалены. Тогда разница (без цвета) выглядит так:

              |  1 foo 8.1047  < del/new
              |  2 bar 6.2343  < del/new
1 foo 0.0000  |  3 foo 0.0000  < match
2 bar 5.3124  |  4 bar 1.4452  < wrong
3 foo 4.5621  |                < new/del
4 bar 6.3914  |                < new/del
5 foo 1.0000  |  5 foo 1.0000  < match
6 bar 6.3212  |  6 bar 7.2321  < wrong

Однако я хочу следующее, чтобы все строки были помечены как неправильные, за исключением совпадающих строк 5:

1 foo 0.0000  |  1 foo 8.1047 < wrong
2 bar 5.3124  |  2 bar 6.2343 < wrong
3 foo 4.5621  |  3 foo 0.0000 < wrong
4 bar 6.3914  |  4 bar 1.4452 < wrong
5 foo 1.0000  |  5 foo 1.0000 < match
6 bar 6.3212  |  6 bar 7.2321 < wrong

person flotzilla    schedule 05.01.2015    source источник
comment
вы можете использовать sdiff file1 file2 вместо vimdiff?   -  person Olivier Dulac    schedule 05.01.2015
comment
@OlivierDulac: Нет, на самом деле, файлы, которые я сравниваю в этих случаях, намного длиннее, и я хочу их прокручивать, поэтому vimdiff в порядке. Я не знал о sdiff, это определенно удобно для сравнения коротких файлов.   -  person flotzilla    schedule 05.01.2015


Ответы (3)


Как насчет использования подключаемого модуля diffchar.vim? Он сравнивает построчно в режиме без сравнения. Пожалуйста, откройте 2 файла в 2 окнах, а затем просто нажмите F7. По умолчанию он пытается найти различия по символам в строке, но вы можете изменить единицы разницы, слова или что-то еще.

person Rick Howe    schedule 06.01.2015
comment
Вау, этот плагин потрясающий! Помимо того факта, что запуск его в режиме без diff действительно делает именно то, что я искал (поэтому я исключил ваш как ответ), он значительно улучшает vimdiff в целом, уменьшая выделение diff до фактических различий! Меня всегда раздражало, что если есть два различия в одной строке, выделяется вся область между этими различиями, а не только фактические различия, которые, например, значительно усложняет сканирование различий двух кодов с переименованной переменной или чем-то в этом роде, и этот плагин полностью решает эту проблему. Большое спасибо! - person flotzilla; 06.01.2015
comment
@RickHowe, ваш плагин просто необходим! - person Enlico; 03.01.2018
comment
Начиная с версии 8.0 плагина это решение больше не работает. @ rick-How, есть ли обходной путь? - person stacksia; 09.01.2019
comment
diffchar.vim теперь работает только в режиме сравнения с версии 8.0. Загрузите github.com/rickhowe/sample/blob/master/mylinediff.vim, чтобы установить параметр difffexpr и проверить построчное содержимое. Не забудьте сделать "diffthis" в обоих окнах. - person Rick Howe; 11.01.2019

Копируя этот пример, я заметил, что vimdiff будет делать то, что вы хотите, если у вас есть номер строки, связанный с каждой строкой.

Следовательно, вы можете использовать cat, чтобы добавить номер строки, а затем diff:

  cat -n file1 > file1_with_line_no
  cat -n file2 > file2_with_line_no

  vimdiff file1_with_line_no file2_with_line_no

Результат будет таким, каким вы хотите (показан с diff для удобства копирования сюда):

 diff file1_with_line_no file2_with_line_no --side-by-side
 1  foo 0.0000                                            |      1  foo 8.1047
 2  bar 5.3124                                            |      2  bar 6.2343
 3  foo 4.5621                                            |      3  foo 0.0000
 4  bar 6.3914                                            |      4  bar 1.4452
 5  foo 1.0000                                                   5  foo 1.0000
 6  bar 6.3212                                            |      6  bar 7.2321

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

linediff() { 
     if [ -z "$1" ] || [ -z "$2" ]; then return; fi
     f1=$(basename "$1")
     f2=$(basename "$2")
     cat -n "$1" > "/tmp/$f1"
     cat -n "$2" > "/tmp/$f2"
     vimdiff "/tmp/$f1" "/tmp/$f2"
     rm "/tmp/$f1" "/tmp/$f2"
 }

и теперь linediff file1 file2 сделает то же самое и уберет после.

person jas_raj    schedule 05.01.2015
comment
Спасибо за ваше предложение. На самом деле это достаточно приличный обходной путь для моего конкретного случая (в котором мне не нужно редактировать файлы), если в vimdiff действительно нет такой функции. Тем не менее, я все еще надеюсь на последнее, поскольку этот обходной путь ломается, как только я хотел отредактировать файлы diff. - person flotzilla; 05.01.2015
comment
Хорошо, я прошел через man diff, но похоже, что такой возможности нет ... Единственное, что я хотя бы сделал, это -d (похоже, --minimal делает то же самое), который, по-видимому, использует еще несколько сложный алгоритм для минимизации различий (хотя никаких дополнительных подробностей по этому поводу не приводится), но, по крайней мере, для моего примера в вопросе он ничего не изменил. - person flotzilla; 05.01.2015
comment
Это так здорово, что я обернул это функцией bash. Надеюсь, вы не возражаете, если я добавлю это к вашему вопросу. Спасибо! - person kabanus; 07.01.2020

Vim использует внешнюю команду diff для анализа двух файлов, поэтому вы можете повлиять на результат с помощью другого инструмента, который использует другой алгоритм. Вы можете настроить это с помощью опции 'diffexpr'; вывод инструмента должен быть в стиле "ed". Cp. :help diff-diffexpr.

Обратите внимание, что это влияет только на добавленные / измененные / удаленные строки; для отображения различий символов в самой измененной строке Vim делает это самостоятельно.

К сожалению, я не знаю ни одного альтернативного инструмента сравнения, который мог бы обеспечить такой вывод, но, возможно, другие смогут его заполнить.

person Ingo Karkat    schedule 05.01.2015
comment
Спасибо за указатель на difffexpr. Я уже был почти уверен, что vimdiff просто использует diff под капотом, теперь я знаю, где искать. Достаточно ли вы знаете diff, чтобы быть уверенным, что этой функции не существует (или вы только что случайно узнали об этом)? (Думаю, мне стоит погрузиться с головой в _2 _...) - person flotzilla; 05.01.2015