Сравните файлы исходного кода, игнорируя различия в форматировании (например, пробелы, переносы строк и & hellip;)

Я ищу приложение, которое может сравнить два источника 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? Иначе, есть ли альтернатива (предпочтительно для командной строки)?

9
задан 8 September 2018 в 18:40

3 ответа

Я сомневаюсь, что это то, что может сделать diff. Если в строке есть пробелы, она будет работать (или другие подобные программы, такие как kompare). В худшем случае вы можете выполнять поиск и замену, а также свернуть символы табуляции и т. Д. Но то, что вы просите для пробелов, меняется за пределами строки ...

Вам понадобится программа, которая понимает язык C ++. Обратите внимание, что все языки разные и, в частности, Python использует пробелы для определения блоков кода. Поэтому я сомневаюсь, что любая общая программа, похожая на diff, будет работать с «любым» (или конкретным) языком программирования.

Вы могли бы рассмотреть какой-то синтаксический анализатор, чтобы просмотреть два исходных файла и затем сравнить выходные данные этого синтаксического анализатора.

Это выходит за рамки моего опыта, но я предлагаю вам взглянуть на Lex и Yacc . Это страницы Википедии; Возможно, вы захотите взглянуть на эту страницу, которая дает краткое объяснение и пример.

0
ответ дан 8 September 2018 в 18:40

Вы можете использовать dwdiff. Из man dwdiff :

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 выше.

0
ответ дан 8 September 2018 в 18:40

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

  1. созданные временные ответвления:

    $ git co feature-a
    $ git co -b 1
    $ git co feature-b
    $ git co -b 2
    
  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
    
  3. сделал фактическое сравнение:

    $ git diff -w -b 1 2
    

    (-w -b позволяет Вам игнорировать различие в пространстве, на всякий случай).

Можно предпочесть uncrustify clang-format (uncrustify mod_full_brace_if может использоваться для осуществления вставки/удаления фигурных скобок вокруг одной строки ifтело).

Кроме того, если GNU parallel не установлен, использовать xargs - это делает то же, но немного дольше.

0
ответ дан 8 September 2018 в 18:40

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

Похожие вопросы: