Я ищу приложение, которое может сравнить два источника C ++ и найти значимые для кода различия (для сравнения версий, которые могли быть переформатированы по-разному). Как минимум, то, что способно игнорировать изменения в пробелах, символах табуляции и новых строках, которые не влияют на функциональность источника (обратите внимание, что вопрос о том, считается ли символ новой строки пробельным , зависит от языка , и C и C ++ делают это). И, в идеале, то, что может точно идентифицировать все значимые для кода различия. Я нахожусь под Ubuntu.
Согласно diff --help | grep ignore
, я ожидал, что diff -bBwZ
выполнит разумно работу (я ожидал получить несколько ложных негативов, о которых мы поговорим позже). Тем не менее, это не так.
если у меня есть следующие файлы с фрагментами
test_diff1.txt
else if (prop == "P1") { return 0; }
и test_diff2.txt
else if (prop == "P1") {
return 0;
}
, то
$ diff -bBwZ test_diff1.txt test_diff2.txt
1c1,3
< else if (prop == "P1") { return 0; }
---
> else if (prop == "P1") {
> return 0;
> }
[ 1114] вместо пустых результатов.
Использование средства форматирования кода в качестве «фильтра» на обоих входах может отфильтровывать эти различия, но затем полученный результат должен быть привязан к исходным входам для окончательного отчета о различиях, чтобы сохранить фактический текст и номера строк. Таким образом, цель достижима без потребности в компиляторе должным образом ... Хотя я не знаю, доступно ли что-то.
Можно ли достичь цели с помощью diff
? Иначе, есть ли альтернатива (предпочтительно для командной строки)?
Я сомневаюсь, что это то, что может сделать diff. Если в строке есть пробелы, она будет работать (или другие подобные программы, такие как kompare). В худшем случае вы можете выполнять поиск и замену, а также свернуть символы табуляции и т. Д. Но то, что вы просите для пробелов, меняется за пределами строки ...
Вам понадобится программа, которая понимает язык C ++. Обратите внимание, что все языки разные и, в частности, Python использует пробелы для определения блоков кода. Поэтому я сомневаюсь, что любая общая программа, похожая на diff, будет работать с «любым» (или конкретным) языком программирования.
Вы могли бы рассмотреть какой-то синтаксический анализатор, чтобы просмотреть два исходных файла и затем сравнить выходные данные этого синтаксического анализатора.
Это выходит за рамки моего опыта, но я предлагаю вам взглянуть на Lex и Yacc . Это страницы Википедии; Возможно, вы захотите взглянуть на эту страницу, которая дает краткое объяснение и пример.
Вы можете использовать dwdiff
. Из man dwdiff
:
blockquote>
dwdiff
- программа различий слов с разделителямиПрограмма очень умная - см.
dwdiff --help
: [ 1111]$ dwdiff --help Usage: dwdiff [OPTIONS] <OLD FILE> <NEW FILE> -h, --help Print this help message -v, --version Print version and copyright information -d <delim>, --delimiters=<delim> Specify delimiters -P, --punctuation Use punctuation characters as delimiters -W <ws>, --white-space=<ws> Specify whitespace characters -u, --diff-input Read the input as the output from diff -S[<marker>], --paragraph-separator[=<marker>] Show inserted or deleted blocks of empty lines, optionally overriding the marker -1, --no-deleted Do not print deleted words -2, --no-inserted Do not print inserted words -3, --no-common Do not print common words -L[<width>], --line-numbers[<width>] Prepend line numbers -C<num>, --context=<num> Show <num> lines of context -s, --statistics Print statistics when done --wdiff-output Produce wdiff compatible output -i, --ignore-case Ignore differences in case -I, --ignore-formatting Ignore formatting differences -m <num>, --match-context=<num> Use <num> words of context for matching --aggregate-changes Allow close changes to aggregate -A <alg>, --algorithm=<alg> Choose algorithm: best, normal, fast -c[<spec>], --color[=<spec>] Color mode -l, --less-mode As -p but also overstrike whitespace -p, --printer Use overstriking and bold text -w <string>, --start-delete=<string> String to mark begin of deleted text -x <string>, --stop-delete=<string> String to mark end of deleted text -y <string>, --start-insert=<string> String to mark begin of inserted text -z <string>, --stop-insert=<string> String to mark end of inserted text -R, --repeat-markers Repeat markers at newlines --profile=<name> Use profile <name> --no-profile Disable profile reading
Проверьте это с помощью:
cat << EOF > test_diff1.txt else if (prop == "P1") { return 0; } EOF cat << EOF > test_diff2.txt else if (prop == "P1") { return 0; } EOF
Затем запустите сравнение:
$ dwdiff test_diff1.txt test_diff2.txt --statistics else if (prop == "P1") { return 0; } old: 9 words 9 100% common 0 0% deleted 0 0% changed new: 9 words 9 100% common 0 0% inserted 0 0% changed
Обратите внимание
100% common
выше.
В аналогичной ситуации, когда я должен был выдержать сравнение два git
ответвления форматирующим код агностическим способом, я сделал это:
созданные временные ответвления:
$ git co feature-a
$ git co -b 1
$ git co feature-b
$ git co -b 2
отформатированный оба использования ответвлений clang-format
:
$ git co 1
$ find . -name '*.cpp' -print0 | parallel -0 -n 1 clang-format -i -style=google
$ git ci -a -m1 --no-verify
$ git co 2
$ find . -name '*.cpp' -print0 | parallel -0 -n 1 clang-format -i -style=google
$ git ci -a -m2 --no-verify
сделал фактическое сравнение:
$ git diff -w -b 1 2
(-w -b
позволяет Вам игнорировать различие в пространстве, на всякий случай).
Можно предпочесть uncrustify
clang-format
(uncrustify
mod_full_brace_if
может использоваться для осуществления вставки/удаления фигурных скобок вокруг одной строки if
тело).
Кроме того, если GNU parallel
не установлен, использовать xargs
- это делает то же, но немного дольше.