Как связать номер строки из файла с файлом результатов параллельного сравнения?

Как связать номер строки из файла с файлом результатов параллельного сравнения?

Мой сценарий таков:

Сначала сгенерируйте рядом diffдва файла, используя:

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

Вывод DiffResult.txt:

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

Теперь давайте скажем, что линия

This is line A

и

This is line B

находятся в строке 5 file1.txtи file2.txtсоответственно. Тогда я должен иметь возможность связать с ним соответствующий номер строки следующим образом:

Желаемый результат 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

Причина, по которой я выбираю этот подход, заключается в том, что если я сгенерирую номера строк до этого diff, то даже при небольшом изменении пробела diffбудет видна разница из-за номеров строк, связанных со строками.

У кого-нибудь есть светлые идеи? Я думаю, это самый сложный вопрос, который когда-либо задавали на StackExchange, я полагаю :D

решение1

Проблему можно решить, отфильтровав вывод diff. Этот пример работает для меня (хотя размещение и размер промежутка между левой/правой сторонами вывода diff, вероятно, будут деталями, которые различаются в разных реализациях):

#!/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;
    }
}
'

Вы не можете добавлять номера строк.до diff, потому что если есть вставки или удаления, номера строк, начинающиеся с этой точки, не будут совпадать, делая различия бесполезными. Мой скрипт вычисляет номера строк для левой/правой стороны разницы в скрипте awk:

  • Сначала он решает, насколько большой должна быть разница, исходя из ширины терминала.
  • Есть (в GNU diff 3.2, который я тестировал)желоб(неиспользуемое пространство) в середине бок о бок различий. Начиная с 80-колоночного терминала, я определил способ вычисления положения желоба.
  • После инициализации скрипт извлекает из каждой строки (в awk, это $0) левую ( textL) и правую ( textR) строки и проверяет, являются ли они пустыми (что произошло бы в случае вставки/удаления).
  • Если левая/правая строки различаются, скрипт реконструирует diffвывод, но добавляет номера строк.

Учитывая это слева

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

yyy

и это справа

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

(10 строк слева, 9 справа), этот скрипт создает

    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                                     <        

Связанный контент