Filtern eines Diff mit einem regulären Ausdruck

  • Es scheint sehr praktisch zu sein, einen Diff so filtern zu können, dass unbedeutende Änderungen nicht angezeigt werden. Ich möchte einen regulären Ausdruck schreiben, der in der Zeile ausgeführt wird, und dann einen anderen String übergeben, der die erfassten Argumente verwendet, um ein kanonisches Formular zu generieren. Wenn die Zeilen davor und danach die gleiche Ausgabe erzeugen, werden sie aus dem Vergleich entfernt.

    Ich arbeite zum Beispiel an einer PHP-Codebasis mit einer signifikanten Anzahl von Arrays Zugriffe werden als my_array[my_key] geschrieben, wenn sie my_array["my_key"] sein sollten, um Probleme zu vermeiden, wenn eine my_key -Konstante definiert ist. Es wäre nützlich, einen diff zu generieren, bei dem die einzige Änderung in der Zeile nicht durch Anführungszeichen erfolgte.

    Ich kann sie nicht alle gleichzeitig ändern, da wir dies nicht tun Ich habe die Ressourcen, um die gesamte Codebasis zu testen, also behebt ich das, wenn ich eine Funktion ändere. Wie kann ich das erreichen? Gibt es etwas Ähnliches, das ich verwenden kann, um ein ähnliches Ergebnis zu erzielen? Eine einfachere Methode könnte beispielsweise darin bestehen, die kanonische Form zu überspringen und einfach zu sehen, ob die Eingabe in die Ausgabe umgewandelt wird. Übrigens, ich benutze Git

    22 November 2011
    Casebash
6 answers
  • Es scheint keine Optionen für Gits diff Befehl, um zu unterstützen, was Sie tun möchten. Sie können jedoch die Umgebungsvariable GIT_EXTERNAL_DIFF und ein benutzerdefiniertes Skript (oder jede ausführbare Datei, die mit Ihrer bevorzugten Skript- oder Programmiersprache erstellt wurde, um einen Patch zu bearbeiten.

    Ich gehe davon aus, dass Sie Linux verwenden. Wenn nicht, können Sie dieses Konzept an Ihre Umgebung anpassen. Angenommen, Sie haben ein Git-Repo, in dem HEAD eine Datei file05 enthält, die Folgendes enthält:

     line 26662: $my_array[my_key]
     

    Und eine Datei file06, die Folgendes enthält:

     line 19768: $my_array[my_key]
    line 19769: $my_array[my_key]
    line 19770: $my_array[my_key]
    line 19771: $my_array[my_key]
    line 19772: $my_array[my_key]
    line 19773: $my_array[my_key]
    line 19775: $my_array[my_key]
    line 19776: $my_array[my_key]
     

    Sie ändern file05 in:

     line 26662: $my_array["my_key"]
     

    Und Sie ändern file06 in:

     line 19768: $my_array[my_key]
    line 19769: $my_array["my_key"]
    line 19770: $my_array[my_key]
    line 19771: $my_array[my_key]
    line 19772: $my_array[my_key]
    line 19773: $my_array[my_key]
    line 19775: $my_array[my_key2]
    line 19776: $my_array[my_key]
     

    Mit dem folgenden Shell-Skript nennen wir es mydiff.sh und platzieren es irgendwo in unserem PATH:

     #!/bin/bash
    echo "$@"
    git diff-files --patch --word-diff=porcelain "${5}" | awk '
    /^-./ {rec = FNR; prev = substr($0, 2);}
    FNR == rec + 1 && /^+./ {
        ln = substr($0, 2);
        gsub("\\[\"", "[", ln);
        gsub("\"\\]", "]", ln);
        if (prev == ln) {
            print " " ln;
        } else {
            print "-" prev;
            print "+" ln;
        }
    }
    FNR != rec && FNR != rec + 1 {print;}
    '
     

    Ausführen des Befehls:

     GIT_EXTERNAL_DIFF=mydiff.sh git --no-pager diff
     

    Wird ausgegeben:

     file05 /tmp/r2aBca_file05 d86525edcf5ec0157366ea6c41bc6e4965b3be1e 100644 file05 0000000000000000000000000000000000000000 100644
    index d86525e..c2180dc 100644
    --- a/file05
    +++ b/file05
    @@ -1 +1 @@
     line 26662: 
     $my_array[my_key]
    ~
    file06 /tmp/2lgz7J_file06 d84a44f9a9aac6fb82e6ffb94db0eec5c575787d 100644 file06 0000000000000000000000000000000000000000 100644
    index d84a44f..bc27446 100644
    --- a/file06
    +++ b/file06
    @@ -1,8 +1,8 @@
     line 19768: $my_array[my_key]
    ~
     line 19769: 
     $my_array[my_key]
    ~
     line 19770: $my_array[my_key]
    ~
     line 19771: $my_array[my_key]
    ~
     line 19772: $my_array[my_key]
    ~
     line 19773: $my_array[my_key]
    ~
     line 19775: 
    -$my_array[my_key]
    +$my_array[my_key2]
    ~
     line 19776: $my_array[my_key]
    ~
     

    Diese Ausgabe zeigt keine Änderungen für die hinzugefügten Anführungszeichen in file05 und file06. Das externe Diff-Skript verwendet grundsätzlich den Git-Befehl diff-files Patchen Sie und filtern Sie die Ausgabe mit einem GNU awk -Skript, um sie zu bearbeiten. Dieses Beispielskript verarbeitet nicht alle verschiedenen Kombinationen aus alten und neuen Dateien, die für GIT_EXTERNAL_DIFF Es gibt auch keinen gültigen Patch aus, aber es sollte ausreichen, um den Einstieg zu erleichtern.

    Sie können Regelmäßige Perl-Ausdrücke , Python difflib oder was auch immer Sie sind

    28 November 2011
    Dan Cruz
  • aus meinem eigenen git --help

    - word-diff-regex = <regex>

    Verwenden Sie <regex>, um zu entscheiden, was ein Wort ist, anstatt Läufe von Nicht-Leerzeichen als ein Wort zu betrachten. Impliziert auch --word-diff, sofern nicht aktiviert wurde. Jede nicht überlappende Übereinstimmung von <regex> wird als Wort betrachtet. Alles zwischen diesen Übereinstimmungen wird als Leerzeichen betrachtet und wird ignoriert (!), Um Unterschiede zu finden. Sie können |[^[:space:]] an Ihren regulären Ausdruck anhängen, um sicherzustellen, dass alle Nicht-Whitespace-Zeichen übereinstimmen. Eine Übereinstimmung, die eine Newline enthält, wird an der Newline automatisch abgeschnitten (!). Der Regex kann auch über einen Diff-Treiber oder eine Konfigurationsoption festgelegt werden. Durch die explizite Angabe von werden alle Diff-Treiber- oder Konfigurationseinstellungen überschrieben. Diff-Treiber überschreiben Konfigurationseinstellungen.

    10 January 2012
    Tay Ray Chuan
  • grepdiff kann zum Filtern der Dunks in der diff-Datei verwendet werden.

     $ git diff -U1 | grepdiff 'console' --output-matching=hunk
     

    Es werden nur die Hunks angezeigt, die mit der angegebenen Zeichenfolge "console" übereinstimmen.

    16 February 2016
    Naga Kiran
  • Normalisieren Sie zunächst die Eingabedateien und vergleichen Sie dann die normalisierten Dateien. Dadurch haben Sie die größte Kontrolle über den Prozess. Z.B. Möglicherweise möchten Sie den Regex nur auf Nicht-HTML-Teile des Codes anwenden, nicht innerhalb von Strings, nicht innerhalb von Kommentaren (oder ignorieren Sie Kommentare insgesamt) Dinge Das Arbeiten mit regulären Ausdrücken in einzelnen Zeilen ist viel fehleranfälliger und höchstens ein Hack.

    Einige Dienstprogramme wie z. meld erlauben das Ausblenden von "unbedeutenden" Unterschieden und kommen mit einer Reihe von Standardmustern, z. Nur Whitespace-Änderungen ausblenden. Ich denke, das ist so ziemlich das, was Sie wollen.

    26 November 2011
    Anony-Moussekseen
  • Wenn das Ziel die Minimierung trivialer Unterschiede ist, können Sie unser SmartDifferencer in Betracht ziehen.

    Diese Tools vergleichen die Sprache der -Syntax , nicht das Layout. Viele triviale Änderungen (Layout, geänderte Kommentare, sogar geänderte Radix-Werte) werden ignoriert nicht gemeldet. Jedes Tool verfügt über einen vollständigen Sprachparser. Es gibt eine Version für viele Sprachen, einschließlich PHP.

    Das Beispiel $ FOO [abc] wird nicht als "semantisch identisch" mit $ FOO ["abc"] behandelt. weil sie nicht sind Wenn abc actaully eine Definition als konstant hat, ist $ FOO ["abc"] nicht semantisch äquivalent.

    27 November 2011
    Casebash
  • Ich verwende einen Ansatz, der git diff kombiniert und einen regulären Ausdruck verwendet, der auf die Ergebnisse passt. In einigen Testcodes (PERL) weiß ich, dass das Testen erfolgreich ist, wenn sich das in den Ergebnisdateien der Tests gespeicherte OutputFingerprint nicht geändert hat.

    Zuerst mache ich ein

     my $matches = `git diff -- mytestfile`
     

    und bewerten Sie dann das Ergebnis:

     if($matches =~ /OutputFingerprint/){
      fail();
      return 1;
    }else{
      ok();
      return 0;
    }
     
    24 November 2011
    eckesDero