比较源代码文件,忽略格式差异(例如空格、换行符等)

比较源代码文件,忽略格式差异(例如空格、换行符等)

我正在寻找一个可以比较两个 C++ 源代码并找到代码意义差异的应用程序(用于比较可能被重新格式化的版本)。至少,它能够忽略空格、制表符和换行符的变化,而不会影响源代码的功能(请注意,换行符是否被视为空格依赖于语言,而 C 和 C++ 也是如此)。而且,理想情况下,可以准确识别所有代码有意义的差异。我在 Ubuntu 下。

按照diff --help | grep ignore我的diff -bBwZ预期合理地这项工作(我预计会得到一些假阴性,稍后处理)。然而,事实并非如此。

如果我有以下带有片段的文件

测试_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;
>     }

而不是空的结果。

使用代码格式化程序作为两个输入的“过滤器”可能会过滤掉这些差异,但随后必须将最终的输出绑定到原始输入,以便最终报告差异以保留实际的文本和行号。因此,无需适当的编译器即可实现目标……但我不知道是否有可用的方法。

能达到目的吗diff 否则,还有其他方法吗(最好是命令行)?

答案1

您可以使用dwdiff。从man dwdiff

dwdiff- 分隔词差异程序

程序非常巧妙 - 参见dwdiff --help

$ 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多于。

答案2

我怀疑 diff 能做到这一点。如果一行中的空格发生变化,那么它就可以工作(或者其他类似程序,如 kompare)。最坏的情况下,您可以进行搜索和替换并折叠制表符等。但您要求的是一行以外的空格变化……

您需要一个能够理解 C++ 语言的程序。请注意,所有语言都是不同的,尤其是 Python,它使用空格来定义代码块。因此,我怀疑任何通用的 diff 类程序都无法与“任何”(或特定)编程语言兼容。

您可能会考虑使用某种解析器来遍历两个源文件,然后比较该解析器的输出。

这超出了我的背景,但我建议你看看莱克斯雅克。这些是维基百科页面;你可能想看看页面提供了简洁的解释和示例。

答案3

在类似的情况下,当我需要以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主体周围插入/删除花括号)。

此外,如果parallel未安装 GNU,请使用xargs- 其功能相同,但时间会稍长一些。

相关内容