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
?で達成できますか?そうでなければ、代替手段があります行)?
dwdiff
を使用できます。 man dwdiff
から:
dwdiff
-区切られたWord diffプログラム
プログラムは非常に賢い-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
に注意してください。
これがdiffでできることだとは思いません。行内にスペースの変更がある場合、それは動作します(またはkompareのような他の同様のプログラム)。さらに悪いことに、タブ文字の検索と置換、折りたたみなどを行うことができます。しかし、空白を求めているのは行を超えて変化します...
C++言語を理解するプログラムが必要です。すべての言語は異なり、特にPythonは空白を使用してコードブロックを定義します。そのため、一般的なdiffのようなプログラムが「任意の」(または特定の)プログラミング言語で動作することを疑います。
何らかの種類のパーサーで2つのソースファイルを調べてから、このパーサーの出力を比較することを検討してください。
これは私の背景を超えていますが、 Lex および Yacc を検討することをお勧めします。これらはウィキペディアのページです。 this ページを見てください。簡潔な説明と例があります。
同様の状況で、コードフォーマットに依存しない方法で2つの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
では、念のためスペースの違いを無視できます)。
clang-format
よりもuncrustify
を好む場合があります(uncrustify
のmod_full_brace_if
は、単一行if
の本体の周りに中括弧の挿入/削除を強制するために使用できます)。
また、GNU parallel
がインストールされていない場合は、xargs
を使用します。これは同じですが、少し長くなります。