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


9

我正在寻找一个可以比较两个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;
>     }

而不是空的结果。

在两个输入上使用代码格式化程序作为“过滤器”可能会过滤掉这些差异,但是最终的输出将不得不与原始输入绑定在一起,以便最终报告差异,以保留实际的文本和行号。因此,不需要适当的编译器就可以实现目标。不过,我不知道是否有可用的东西。

可以达到目的diff吗? 否则,是否有替代方法(最好是用于命令行)?

Answers:


6

您可以使用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上面。


1

我怀疑这是diff可以做到的。如果一行中的空间有变化,那么它将起作用(或像kompare这样的其他类似程序)。更糟糕的是,您可以执行搜索和替换以及折叠制表符等操作。但是,您要求的空格更改超出了一行...

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

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

这超出了我的背景,但是我建议您研究LexYacc。这些是维基百科页面;您可能想看看页面,页面提供了简洁的说明和示例。


我认为我不需要特别了解C ++的东西(至少是为了忽略由于换行符引起的差异),我不需要编译源代码。无论使用哪种语言,都只需要适当地进行比较即可。实际上,还有另一个建议建议使用dwdiff。仍然必须对其进行测试,但是提供的示例令人信服。
sancho.s ReinstateMonicaCellio

Lex / Yacc本身并不编译源代码。它将把它分成令牌。例如,如果您具有“ int foo = 0”和“ int bar = 0”,则显然foo和bar是两个不同的单词;但在程序的上下文中,它们实际上是相同的。如果要捕获类似的内容,则可能需要某种解析器。如果您不这样做,那么dwdiff的建议确实是一个很好的建议。祝好运!

0

在类似的情况下,当我需要以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以防万一,您可以忽略空格差)。

您可能喜欢uncrustifyclang-formatuncrustifymod_full_brace_if可用于强制插入/移除周围的单线的大括号if的身体)。

另外,如果parallel未安装GNU ,请使用xargs-它会执行相同的操作,但是会更长一点。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.