Wie ordnet man der Side-by-Side-Diff-Ausgabeergebnisdatei eine Zeilennummer einer Datei zu?

Wie ordnet man der Side-by-Side-Diff-Ausgabeergebnisdatei eine Zeilennummer einer Datei zu?

Mein Szenario ist folgendes:

diffGenerieren Sie zunächst zwei Dateien nebeneinander mit:

diff -y --supress-common-lines file1.txt file2.txt > DiffResult.txt

Ausgabe von DiffResult.txt:

   file1.txt             file2.txt
This is line A    |   This is line B
This is line C    |   This is line D

Nehmen wir nun die Zeile

This is line A

Und

This is line B

befinden sich in Zeile 5 von file1.txtbzw. file2.txtDann sollte ich in der Lage sein, die entsprechende Zeilennummer wie folgt zuzuordnen:

Gewünschte Ausgabe von DiffResult.txt:

      file1.txt                file2.txt
5   This is line A    |  5   This is line B
7   This is line C    |  7   This is line D

Der Grund, warum ich diesen Ansatz wähle, liegt darin, dass, wenn ich die Zeilennummern vor generiere diff, sogar bei einer kleinen Änderung der Leerzeichen diffein Unterschied angezeigt würde, da den Zeilennummern die Zeilennummern zugeordnet sind.

Hat jemand gute Ideen? Ich glaube, das ist die schwierigste Frage, die jemals bei StackExchange gestellt wurde :D

Antwort1

Das Problem kann durch Filtern der Ausgabe von gelöst werden diff. Dieses Beispiel funktioniert bei mir (obwohl die Platzierung und Größe des Randes zwischen den linken und rechten Seiten der Diff-Ausgabe wahrscheinlich ein Detail ist, das sich zwischen den Implementierungen unterscheidet):

#!/bin/sh
# $Id: diff-two-column,v 1.2 2016/09/26 20:38:32 tom Exp $
# see http://unix.stackexchange.com/questions/312025/how-to-associate-line-number-from-a-file-to-the-side-by-side-diff-output-result

usage() {
    cat >&2 <<EOF
usage: $0 file1 file2
EOF
    exit 1
}

[ $# = 2 ] || usage
[ -f "$1" ] || usage
[ -f "$2" ] || usage

width=${COLUMNS:-80}
check=$(stty size|cut -d' ' -f2)
[ -n "$check" ] && width=$check

diff -W $width -y "$1" "$2" | \
expand | \
awk -v width=$width '
BEGIN {
    L=0;
    R=0;
    gutter = width / 2;
    half = gutter - 2;
}
{
    textL = substr($0, 1, half - 1);
    sub("[ ]+$", "", textL);  # trim trailing blanks

    # The script relies on correctly extracting textM, the gutter:
    # if lines differ,    textM is " ! "
    # if line inserted,   textM is " > "
    # if line deleted,    textM is " < "
    # if lines unchanged, textM is "   "
    textM = substr($0, gutter - 2, 3);

    textR = ( length($0) > gutter ) ? substr($0, gutter+1, half) : "";

    if ( textM != " > " ) {
         L++;
    }
    if ( textM != " < " ) {
         R++;
    }

    if ( textL != textR ) {
        # printf "SHOW %s\n", $0;
        # printf "gap \"%s\"\n", textM;
        # printf "<<< \"%s\"\n", textL;
        # printf ">>> \"%s\"\n", textR;
        if ( textL == "" ) {
            printf "%5s %-*s %-3s %5d %s\n",
                " ", half, textL,
                textM,
                R, textR;
        } else if ( textR == "" ) {
            printf "%5d %-*s %-3s %5s %s\n",
                L, half, textL,
                textM,
                " ", textR;
        } else {
            printf "%5d %-*s %-3s %5d %s\n",
                L, half, textL,
                textM,
                R, textR;
        }
    } else {
        # printf "SKIP %s\n", $0;
    }
}
'

Sie können keine Zeilennummern hinzufügenVor diff, denn wenn Einfügungen oder Löschungen vorhanden sind, stimmen die Zeilennummern ab diesem Punkt nicht überein, wodurch die Unterschiede nicht nützlich sind. Mein Skript berechnet die Zeilennummern für die linke/rechte Seite des Unterschieds im awk-Skript:

  • Zunächst wird basierend auf der Breite des Terminals entschieden, wie breit der Diff sein soll.
  • Es gibt (in GNU diff 3.2, das ich getestet habe) eineRinne(ungenutzter Platz) in der Mitte der nebeneinander liegenden Unterschiede. Ausgehend von einem 80-Spalten-Terminal habe ich eine Möglichkeit gefunden, die Position des Randes zu berechnen.
  • Nach der Initialisierung extrahiert das Skript aus jeder Zeile (in awkist dies $0) die linken ( textL) und rechten ( textR) Zeichenfolgen und prüft, ob sie leer sind (was bei einem Einfügen/Löschen passieren würde).
  • Wenn die linken und rechten Zeilen unterschiedlich sind, rekonstruiert das Skript die diffAusgabe, fügt jedoch die Zeilennummern hinzu.

Angesichts dessen auf der linken

1
2
3
4
This is line A
6
This is line C
123456789.123456789.123456789.123456789.123456789.

yyy

und das hier rechts

1
2
3
4
This is line B
6
This is line D
abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.
xxx

(10 Zeilen links, 9 rechts), dieses Skript erzeugt

    5 This is line A                          |      5 This is line B
    7 This is line C                          |      7 This is line D
    8 123456789.123456789.123456789.1234567   |      8 abcdefghi.abcdefghi.abcdefghi.abcdefg
                                              |      9 xxx
   10 yyy                                     <        

verwandte Informationen