
私のシナリオは次のとおりです:
diff
まず、次を使用して 2 つのファイルを並べて生成します。
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
file1.txt
はそれぞれとの 5 行目にあります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 <