書式の違い(空白、改行など)を無視して、ソースコードファイルを比較します。


9

2つの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か? それ以外の場合、代替手段はありますか(できれば、コマンドライン)?

回答:


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のようなプログラムが「任意の」(または特定の)プログラミング言語で動作することは疑わしいと思います。

ある種のパーサーで2つのソースファイルを調べ、このパーサーの出力を比較することを検討する場合があります。

これは私の背景を超えていますが、LexYaccを調べることをお勧めします。これらはウィキペディアのページです。簡潔な説明と例が記載されているこのページをご覧ください。


特にC ++を理解できるものは必要ないと思います(少なくとも改行による違いを無視するため)。ソースをコンパイルする必要はありません。言語に関係なく、適切に比較する必要があるだけです。実際には、dwdiffを示唆する別の答えがあります。それでもテストする必要がありますが、提供されている例には説得力があります。
sancho.s ReinstateMonicaCellio 2018

Lex / Yacc自体は、ソースコードをコンパイルしません。それはトークンに分割されます。たとえば、 "int foo = 0"と "int bar = 0"がある場合、fooとbarは明らかに2つの異なる単語です。しかし、プログラムのコンテキストでは、それらは実際には同じです。このような類似点をキャッチしたい場合は、何らかのパーサーが必要になる場合があります。そうしないと、確かに、dwdiffの提案は非常に良い提案のように見えます。幸運を!
Ray

0

同様の状況で、gitコード形式にとらわれない方法で2つのブランチを比較する必要がある場合、これを行いました。

  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-formatuncrustifyのはmod_full_brace_ifシングルラインの周りの中括弧の挿入/除去強制するために使用することができるifの体を')。

また、GNU parallelがインストールされていない場合は、使用しますxargs。同じように機能しますが、少し長くなります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.