Как игнорировать перемещенные линии в diff

11

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

Однако это оказывается сложнее, чем можно подумать, потому что инструмент выводит строки, в которых порядок не имеет значения (например, importоператоры, объявления функций и т. Д.), В полуслучайном порядке. Из-за этого выходные данные diffзагромождены многими изменениями, которые фактически являются только строками, перемещенными в другую позицию в том же файле.

Есть ли способ заставить diff игнорировать эти шаги и выводить только те строки, которые действительно были добавлены или удалены?

dnadlinger
источник
Может быть, проще изменить свой инструмент для генерации функций и импорта объявлений в определенном (например, лексикографическом, если возможно на вашем языке) порядке?
Даниэль Бек
@ Даниэль Бек: Смотрите мой комментарий к ответу Жиля ниже.
dnadlinger
Старая тема, но суммируя комментарии ниже, как этот diffинструмент сможет отделить действительные ходы от недействительных, так как порядок инструкций в коде имеет значение, и случаи, когда это не так, ограничены (импорт, объявление функций и классов, так далее.) ?
Жоэль
@ Joël: Ответ прост: я знал, что изменения генератора, которые я должен был протестировать, не приведут к ошибкам, связанным с изменением порядка строк. Конечно, вам нужен инструмент, основанный на парсере для целевого языка, чтобы избежать ложных срабатываний в общем случае (или просто комплексный набор тестов для вашего генератора), но это должна была быть быстрая разовая проверка в дополнение к обзору кода.
dnadlinger

Ответы:

2

Вы можете сделать простой diff, сохранить результат где-нибудь (чтобы избежать другого diff), пройти через линии в любой версии, а затем удалить их с другой стороны.

Это породило отдельный проект для рабочего кода. Код.

l0b0
источник
Я не уверен, что именно он должен делать, но, похоже, он не дает желаемых результатов. Как я понимаю вопрос, из двух примеров в коде /tmp/oldи /tmp/newрезультатов различий не будет, так как есть только строки, которые были перемещены. Этот код, однако, дает результаты.
Илари Каджасте
Исправлен код.
10
Я не проверял ответ, так как я давно закончил процесс объединения, упомянутый выше, но с первого взгляда на код он выглядит так, как будто он может работать.
dnadlinger
4

Вы можете попытаться отсортировать их в первую очередь. Что-то вроде:

sort file-a > s-file-a
sort file-b > s-file-b
diff s-file-a s-file-b

Bash (и zsh) могут сделать это в одной строке с подстановкой процесса

diff <(sort file-a) <(sort file-b)
Кир
источник
Это может быть вариантом, но сгенерированные различия не будут очень полезны, потому что я потеряю всю информацию о номере строки и контексте ...
dnadlinger
Даже если я все еще надеюсь на лучшее решение, я использовал этот подход для проверки пакета изменений, над которым я работал.
dnadlinger
2
Я могу предвидеть, где это пропустит некоторые изменения. Иногда порядок имеет значение, иногда нет. Вы отбрасываете весь контекст.
Rich Homolka
Для заказа рефактора, где я хотел убедиться, что все, что существовало, все еще работает, это было именно то, что мне нужно.
ntrrobng
0

Похоже, у вас есть контроль над инструментом. Затем сделайте его вывод предсказуемым: вместо генерации объявлений в полуслучайном порядке используйте (скажем) алфавитный порядок в качестве последнего средства. Это позволит не только удалить бесполезные помехи из различий, но и упростить чтение и проверку выходных данных инструмента для человека.

Жиль "ТАК - перестань быть злым"
источник
Извините, но этот ответ мне совсем не помогает - если бы это было так просто, я бы сразу его изменил. Кроме того, в настоящее время я объединяю изменения из проекта, из которого изначально был создан генератор, поэтому добавление такого довольно далеко идущего изменения усложнит этот процесс еще больше…
dnadlinger
0

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

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

csplit all-07sep2015-11:19:12.sql '/Current Database/-1' '{*}'  # split the dump made before the change, creating files xx00, xx01, ...
csplit -f yy all-07sep2015-12:26:12.sql '/Current Database/-1' '{*}' # split the dump made after the change, creating files yy00, yy01, ...
fgrep 'Current Database' xx?? yy?? | perl -lne 'BEGIN{my %foo}; /(^....).*`(.*)`/ and push(@{$foo{lc($2)}}, $1); END {printf("diff -di %s %s\n", @{$_}) for values %foo}' | sh -x | less  # match the pairs and compare them with diff
reinierpost
источник