Vergleichen Sie Quellcodedateien und ignorieren Sie Formatierungsunterschiede (wie Leerzeichen, Zeilenumbrüche usw.).

9

Ich suche nach einer Anwendung, die zwei C ++ - Quellen vergleichen und die codebedeutenden Unterschiede finden kann (um Versionen zu vergleichen, die möglicherweise anders formatiert wurden). Zumindest etwas, das Änderungen in Leerzeichen, Tabulatoren und Zeilenumbrüchen ignorieren kann, die die Funktionalität der Quelle nicht beeinträchtigen (beachten Sie, dass es sprachabhängig ist, ob ein Zeilenumbruch als Leerzeichen betrachtet wird , und C und C ++ dies tun ). Und im Idealfall etwas, das genau alle codebedeutenden Unterschiede identifizieren kann. Ich bin unter Ubuntu.

Wie pro diff --help | grep ignoreerwartete ich diff -bBwZtun vernünftigerweise den Job (ich erwartet hatte einige falsche Negative zu bekommen, um später behandelt werden). Trotzdem nicht.

wenn ich die folgenden Dateien mit Schnipsel habe

test_diff1.txt

    else if (prop == "P1") { return 0; }

und test_diff2.txt

    else if (prop == "P1") {
        return 0;
    }

dann

$ diff -bBwZ test_diff1.txt test_diff2.txt
1c1,3
<     else if (prop == "P1") { return 0; }
---
>     else if (prop == "P1") {
>         return 0;
>     }

statt leerer Ergebnisse.

Die Verwendung eines Code-Formatierers als "Filter" für beide Eingaben kann diese Unterschiede herausfiltern, aber dann müsste die resultierende Ausgabe für die endgültige Meldung von Unterschieden an die ursprünglichen Eingaben gebunden werden, um die tatsächlichen Text- und Zeilennummern beizubehalten. Das Ziel ist also erreichbar, ohne dass ein Compiler richtig benötigt wird ... Ich weiß jedoch nicht, ob etwas verfügbar ist.

Kann das Ziel erreicht werden diff? Gibt es sonst eine Alternative (vorzugsweise für die Kommandozeile)?

sancho.s ReinstateMonicaCellio
quelle

Antworten:

6

Sie können verwenden dwdiff. Von man dwdiff:

dwdiff - ein Programm mit begrenzten Wortdifferenzen

Programm ist sehr clever - siehe 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

Testen Sie es mit:

cat << EOF > test_diff1.txt
    else if (prop == "P1") { return 0; }
EOF

cat << EOF > test_diff2.txt
    else if (prop == "P1") {
        return 0;
    }
EOF

Starten Sie dann den Vergleich:

$ 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

Bitte beachten Sie 100% commonoben.

N0rbert
quelle
1

Ich bezweifle, dass dies etwas ist, was Diff tun kann. Wenn sich innerhalb einer Zeile Leerzeichen ändern, funktioniert dies (oder andere ähnliche Programme wie kompare). Schlimmer noch, Sie können Tabulatorzeichen usw. suchen, ersetzen und reduzieren usw. Aber was Sie nach Leerzeichen fragen, ändert sich über eine Zeile hinaus ...

Sie benötigen ein Programm, das die C ++ - Sprache versteht. Beachten Sie, dass alle Sprachen unterschiedlich sind und insbesondere Python Leerzeichen verwendet, um Codeblöcke zu definieren. Daher bezweifle ich, dass ein allgemeines diff-ähnliches Programm mit "jeder" (oder einer bestimmten) Programmiersprache funktionieren würde.

Sie könnten eine Art Parser in Betracht ziehen, um die beiden Quelldateien zu durchsuchen und dann die Ausgaben dieses Parsers zu vergleichen.

Dies geht über meinen Hintergrund hinaus, aber ich schlage vor, Sie schauen sich Lex und Yacc an . Dies sind Wikipedia-Seiten; Vielleicht möchten Sie einen Blick auf diese Seite werfen, die eine kurze Erklärung und ein Beispiel enthält.

Strahl
quelle
Ich glaube nicht, dass ich etwas brauche, das C ++ besonders versteht (zumindest um Unterschiede aufgrund von Zeilenumbrüchen zu ignorieren), ich muss die Quellen nicht kompilieren. Es muss sich nur angemessen unterscheiden, unabhängig von der Sprache. Es gibt tatsächlich eine andere Antwort, die dwdiff vorschlägt. Ich muss es noch testen, aber das Beispiel sieht überzeugend aus.
sancho.s ReinstateMonicaCellio
Lex / Yacc kompiliert den Quellcode nicht per se. Es würde es in Token trennen. Wenn Sie beispielsweise "int foo = 0" vs "int bar = 0" hatten, sind foo und bar eindeutig zwei verschiedene Wörter. aber im Kontext eines Programms sind sie tatsächlich identisch. Wenn Sie Ähnlichkeiten wie diese erkennen möchten, benötigen Sie möglicherweise eine Art Parser. Wenn Sie dies nicht tun, scheint der dwdiff-Vorschlag tatsächlich sehr gut zu sein. Viel Glück!
Ray
0

In einer ähnlichen Situation habe ich Folgendes gitgetan , als ich zwei Zweige unabhängig voneinander auf Code-Formatierung vergleichen musste:

  1. temporäre Zweige erstellt:

    $ git co feature-a
    $ git co -b 1
    $ git co feature-b
    $ git co -b 2
    
  2. formatierte beide Zweige mit 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. tat tatsächlichen Vergleich:

    $ git diff -w -b 1 2
    

    ( -w -bErmöglicht es Ihnen, Platzunterschiede für alle Fälle zu ignorieren).

Sie können es vorziehen , uncrustifyüber clang-format( uncrustify‚s mod_full_brace_ifverwendet werden kann , Einfügen / Entfernen von geschweiften Klammern um einzeiligen zu erzwingen if‘ s Körper).

Wenn GNU parallelnicht installiert ist, verwenden Sie xargs- es funktioniert genauso, jedoch etwas länger.

Andrey Starodubtsev
quelle