回答:
wdiff -w "$(tput bold;tput setaf 1)" -x "$(tput sgr0)" -y "$(tput bold;tput setaf 2)" -z "$(tput sgr0)" file1 file2
dwdiff
主に互換性wdiff
がありますが、色付きの出力とおそらく他の機能もサポートするツールもあります。また、Archなどの一部のLinuxディストリビューションでより多く利用できます。
wdiff -n a b | colordiff
、アドバイスしman colordiff
ます。
git-diffを使用するもう1つの方法:
git diff -U0 --word-diff --no-index -- foo bar | grep -v ^@@
差分の位置に関心がない場合は、grep -v。
私はこれに使用vimdiff
しました。
ここに、 1つまたは2つの小さな文字の違いを示すスクリーンショット(私のスクリーンショットではありません)があります。あまりにも簡単なチュートリアル。
vimdiff -c 'set wrap' -c 'wincmd w' -c 'set wrap' a b
、stackoverflow.com/ a/ 45333535/2097284を提案します。
ここに「あなたを噛んだ犬の髪」の方法
diff
があります... この点にあなたを連れて行きました; それを使用してさらに先に進みます...
サンプル行のペアを使用した場合の出力☻
は次のとおりです... TABを示します
Paris in the spring
Paris in the the spring
vvvv ^
A ca t on a hot tin roof.
a cant on a hot in roof
║ v ^ ^
the quikc brown box jupps ober the laze dogs
The☻qui ckbrown fox jumps over the lazy dogs
║ ║ ^ ║ ║ ║ ║ ║ ^
スクリプトは次のとおりです。行ペアを何らかの方法でフェレットアウトする必要があります。スクリプトは、私にとっては1日で十分でした:) ..それは十分にシンプルであるに違いないと思いますが、私はコーヒーブレイクを予定しています....
#
# Name: hair-of-the-diff
# Note: This script hasn't been extensively tested, so beware the alpha bug :)
#
# Brief: Uses 'diff' to identify the differences between two lines of text
# $1 is a filename of a file which contains line pairs to be processed
#
# If $1 is null "", then the sample pairs are processed (see below: Paris in the spring
#
# ║ = changed character
# ^ = exists if first line, but not in second
# v = exists if second line, but not in first
bname="$(basename "$0")"
workd="/tmp/$USER/$bname"; [[ ! -d "$workd" ]] && mkdir -p "$workd"
# Use $1 as the input file-name, else use this Test-data
# Note: this test loop expands \t \n etc ...(my editor auto converts \t to spaces)
if [[ "$1" == '' ]] ;then
ifile="$workd/ifile"
{ while IFS= read -r line ;do echo -e "$line" ;done <<EOF
Paris in the spring
Paris in the the spring
A cat on a hot tin roof.
a cant on a hot in roof
the quikc brown box jupps ober the laze dogs
The\tquickbrown fox jumps over the lazy dogs
EOF
} >"$ifile"
else
ifile="$1"
fi
#
[[ -f "$ifile" ]] || { echo "ERROR: Input file NOT found:" ;echo "$ifile" ;exit 1 ; }
#
# Check for balanced pairs of lines
ilct=$(<"$ifile" wc -l)
((ilct%2==0)) || { echo "ERROR: Uneven number of lines ($ilct) in the input." ;exit 2 ; }
#
ifs="$IFS" ;IFS=$'\n' ;set -f
ix=0 ;left=0 ;right=1
while IFS= read -r line ;do
pair[ix]="$line" ;((ix++))
if ((ix%2==0)) ;then
# Change \x20 to \x02 to simplify parsing diff's output,
#+ then change \x02 back to \x20 for the final output.
# Change \x09 to \x01 to simplify parsing diff's output,
#+ then change \x01 into ☻ U+263B (BLACK SMILING FACE)
#+ to the keep the final display columns in line.
#+ '☻' is hopefully unique and obvious enough (otherwise change it)
diff --text -yt -W 19 \
<(echo "${pair[0]}" |sed -e "s/\x09/\x01/g" -e "s/\x20/\x02/g" -e "s/\(.\)/\1\n/g") \
<(echo "${pair[1]}" |sed -e "s/\x09/\x01/g" -e "s/\x20/\x02/g" -e "s/\(.\)/\1\n/g") \
|sed -e "s/\x01/☻/g" -e "s/\x02/ /g" \
|sed -e "s/^\(.\) *\x3C$/\1 \x3C /g" \
|sed -n "s/\(.\) *\(.\) \(.\)$/\1\2\3/p" \
>"$workd/out"
# (gedit "$workd/out" &)
<"$workd/out" sed -e "s/^\(.\)..$/\1/" |tr -d '\n' ;echo
<"$workd/out" sed -e "s/^..\(.\)$/\1/" |tr -d '\n' ;echo
<"$workd/out" sed -e "s/^.\(.\).$/\1/" -e "s/|/║/" -e "s/</^/" -e "s/>/v/" |tr -d '\n' ;echo
echo
((ix=0))
fi
done <"$ifile"
IFS="$ifs" ;set +f
exit
#
wdiff
実際には、ファイルを単語ごとに比較する非常に古い方法です。ファイルを再フォーマットし、それを使用diff
して相違点を見つけ、それを再度渡すことで機能しました。私自身はコンテキストを追加することを提案しました。そのため、単語ごとに比較するのではなく、各単語を他の「コンテキスト」単語に囲まれて比較します。これにより、diffはファイル内の一般的なパッセージでそれ自体をよりよく同期できます。特に、一般的な単語の数ブロックだけでファイルがほとんど異なる場合はそうです。たとえば、盗作や再利用のためにテキストを比較する場合。
dwdiff
後にから作成されましたwdiff
。しかし dwdiff
、そのテキスト再フォーマット機能を使用して、で効果を発揮しdwfilter
ます。これはすばらしい開発です。つまり、あるテキストを別のテキストに合わせて再フォーマットし、行ごとのグラフィカルな差分表示を使用してそれらを比較できることを意味します。たとえば、「diffuse」グラフィカルdiffで使用します。
dwfilter file1 file2 diffuse -w
これは、再フォーマットfile1
の形式にfile2
し、それに与えるdiffuse
視覚的な比較のために。file2
は変更されていないため、で単語の違いを直接編集およびマージできますdiffuse
。編集する場合file1
、-r
どのファイルを再フォーマットするかを逆に追加できます。試してみると、非常に強力です。
グラフィカルなdiff(上記を参照)の好みは、diffuse
はるかにクリーンで便利だと感じるためです。また、スタンドアロンのPythonプログラムであるため、他のUNIXシステムに簡単にインストールして配布できます。
他のグラフィカルな差分には多くの依存関係があるようですが、使用することもできます(選択)。これらには、kdiff3
またはが含まれますxxdiff
。
@ Peter.Oのソリューションを基礎として使用して、多くの変更を加えるために書き直しました。
./hairOfTheDiff.sh file1.txt file2.txt
demo
ソースを見てください。これによりpaste
、複数のファイル記述子を使用して、2つの別々の入力用のファイルも必要ないように、空想的なパイピングへの扉が開かれる可能性があります。ハイライトなしは、文字が両方の行にあったことを意味し、ハイライトは最初の行にあったことを意味し、赤は2番目の行にあったことを意味します。
色はスクリプトの上部にある変数を介して変更でき、通常の文字を使用して違いを表現することにより、色を完全に無視することさえできます。
#!/bin/bash
same='-' #unchanged
up='△' #exists in first line, but not in second
down='▽' #exists in second line, but not in first
reset=''
reset=$'\e[0m'
same=$reset
up=$reset$'\e[1m\e[7m'
down=$reset$'\e[1m\e[7m\e[31m'
timeout=1
if [[ "$1" != '' ]]
then
paste -d'\n' "$1" "$2" | "$0"
exit
fi
function demo {
"$0" <<EOF
Paris in the spring
Paris in the the spring
A cat on a hot tin roof.
a cant on a hot in roof
the quikc brown box jupps ober the laze dogs
The quickbrown fox jumps over the lazy dogs
EOF
}
# Change \x20 to \x02 to simplify parsing diff's output,
#+ then change \x02 back to \x20 for the final output.
# Change \x09 to \x01 to simplify parsing diff's output,
#+ then change \x01 into → U+1F143 (Squared Latin Capital Letter T)
function input {
sed \
-e "s/\x09/\x01/g" \
-e "s/\x20/\x02/g" \
-e "s/\(.\)/\1\n/g"
}
function output {
sed -n \
-e "s/\x01/→/g" \
-e "s/\x02/ /g" \
-e "s/^\(.\) *\x3C$/\1 \x3C /g" \
-e "s/\(.\) *\(.\) \(.\)$/\1\2\3/p"
}
ifs="$IFS"
IFS=$'\n'
demo=true
while IFS= read -t "$timeout" -r a
do
demo=false
IFS= read -t "$timeout" -r b
if [[ $? -ne 0 ]]
then
echo 'No corresponding line to compare with' > /dev/stderr
exit 1
fi
diff --text -yt -W 19 \
<(echo "$a" | input) \
<(echo "$b" | input) \
| \
output | \
{
type=''
buf=''
while read -r line
do
if [[ "${line:1:1}" != "$type" ]]
then
if [[ "$type" = '|' ]]
then
type='>'
echo -n "$down$buf"
buf=''
fi
if [[ "${line:1:1}" != "$type" ]]
then
type="${line:1:1}"
echo -n "$type" \
| sed \
-e "s/[<|]/$up/" \
-e "s/>/$down/" \
-e "s/ /$same/"
fi
fi
case "$type" in
'|')
buf="$buf${line:2:1}"
echo -n "${line:0:1}"
;;
'>')
echo -n "${line:2:1}"
;;
*)
echo -n "${line:0:1}"
;;
esac
done
if [[ "$type" = '|' ]]
then
echo -n "$down$buf"
fi
}
echo -e "$reset"
done
IFS="$ifs"
if $demo
then
demo
fi
シンプルなワンライナーは次のとおりです。
diff -y <(cat a.txt | sed -e 's/,/\n/g') <(cat b.txt | sed -e 's/,/\n/g')
アイデアは、カンマ(または使用する区切り文字)を使用して改行で置き換えることですsed
。diff
その後、残りを処理します。
コマンドラインで、ファイルを比較する前に適切な改行を追加するようにします。sed、awk、perlなどを実際に使用して、何らかの体系的な方法で改行を追加できます。ただし、追加しすぎないようにしてください。
しかし、単語の違いを強調するためにvimを使用するのが最善だと思います。vimは、あまり多くの違いがなく、違いが単純な場合に適しています。
私があなたの質問を正しく読んでいるなら、私diff -y
はこの種のものに使用します。
どの行が違いを投げているのかを見つけるために、横並びの比較をはるかに簡単にします。
同じ問題があり、粒度を指定できるオンラインツールPHP Fine Diffで解決しました。技術的には* nixツールではないことは知っていますが、一度だけ文字レベルの差分をとるためだけにプログラムをダウンロードしたくはありませんでした。