답변:
wdiff -w "$(tput bold;tput setaf 1)" -x "$(tput sgr0)" -y "$(tput bold;tput setaf 2)" -z "$(tput sgr0)" file1 file2
wdiff a b | colordiff
dwdiff
과 대부분 호환 도구 wdiff
뿐만 아니라 색깔의 출력과 아마 몇 가지 다른 기능을 지원합니다. 그리고 Arch와 같은 일부 Linux 배포판에서 더 많이 사용할 수 있습니다.
wdiff -n a b | colordiff
, 조언합니다 man colordiff
.
git-diff를 사용하는 또 다른 방법 :
git diff -U0 --word-diff --no-index -- foo bar | grep -v ^@@
diff의 위치에 관심이 없다면 grep -v.
나는 이것을 위해 사용 vimdiff
했다.
여기에 눈에 띄지 않는 스크린 샷이 있습니다. 너무 빠른 튜토리얼 .
vimdiff -c 'set wrap' -c 'wincmd w' -c 'set wrap' a b
제안 합니다.
여기에 ... 방법은 "당신을 비트 개의 ..hair"입니다
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
║ ║ ^ ║ ║ ║ ║ ║ ^
스크립트는 다음과 같습니다. 어떻게 든 행 쌍을 페럿해야합니다. (오늘 전에 diff를 한 번만 사용 했으므로 (두 번?) 많은 옵션을 알지 못하고 옵션을 정렬하지 못합니다. 스크립트는 하루 동안 충분했습니다 :) .. 나는 그것이 충분히 간단해야한다고 생각하지만, 커피 브레이크가 필요합니다 ....
#
# 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
. 이것은 대단한 발전입니다. 즉, 한 텍스트를 다른 텍스트와 일치하도록 다시 포맷 한 다음 라인 별 그래픽 차이 표시기를 사용하여 비교할 수 있습니다. 예를 들어, "확산"그래픽 diff ....와 함께 사용
dwfilter file1 file2 diffuse -w
이것은 형식 file1
을 재 형식화 하고 시각적 비교 file2
를 diffuse
위해 제공합니다 . file2
은 수정되지 않았으므로에서 단어 차이를 직접 편집하여 단어 차이를 병합 할 수 있습니다 diffuse
. 편집하려는 경우 다시 포맷 할 파일을 역으로 file1
추가 할 수 있습니다 -r
. 그것을 시도하고 당신은 그것이 매우 강력하다는 것을 알게 될 것입니다!
그래픽 diff (위 그림 참조)에 대한 나의 선호 diffuse
는 훨씬 깨끗하고 유용하다고 느끼는 것입니다. 또한 독립형 파이썬 프로그램이므로 다른 UNIX 시스템에 쉽게 설치하고 배포 할 수 있습니다.
다른 그래픽 차이에는 많은 의존성이있는 것처럼 보이지만 사용할 수도 있습니다 (선택). 여기에는 kdiff3
또는 이 포함됩니다 xxdiff
.
@ Peter.O의 솔루션 을 기본으로 사용하여 여러 가지 변경을 위해 다시 작성했습니다.
./hairOfTheDiff.sh file1.txt file2.txt
demo
소스를 살펴보십시오 . 이것은 paste
여러 파일 디스크립터를 사용하여 두 개의 개별 입력에 대한 파일이 필요하지 않도록 멋진 배관의 문을 열 수 있습니다 .강조 표시 없음은 문자가 두 줄에 있음을 의미하고 강조 표시는 첫 번째 문자에 있음을 의미하고 빨간색은 두 번째 문자에 있음을 의미합니다.
색상은 스크립트 상단의 변수를 통해 변경 가능하며 일반 문자를 사용하여 차이점을 표현함으로써 색상을 완전히 포기할 수도 있습니다.
#!/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
그런 다음 나머지를 처리합니다.
.csv
쉽게 만들 수 있으며 수식 (A7==K7) ? "" : "diff"
또는 이와 유사한 것을 삽입하여 복사하여 붙여 넣을 수 있습니다.커맨드 라인에서 파일을 비교하기 전에 적절한 줄 바꿈을 추가해야합니다. sed, awk, perl 등을 사용하여 체계적인 방식으로 줄 바꿈을 추가 할 수 있습니다. 너무 많이 추가하지 마십시오.
그러나 단어 차이를 강조 표시하는 vim을 사용하는 것이 가장 좋습니다. 차이가 너무 많지 않고 단순하면 vim이 좋습니다.
귀하의 질문을 올바르게 읽으면 diff -y
이런 종류의 것을 사용합니다.
차이를 던지는 행을 찾기 위해 병렬 비교를 훨씬 간단하게 만듭니다.
나는 같은 문제가 있었고 세분성을 지정할 수있는 온라인 도구 인 PHP Fine Diff로 해결했습니다 . 나는 그것이 기술적으로 * nix 도구가 아니라는 것을 알고 있지만, 한 번만 문자 수준 diff를하기 위해 프로그램을 다운로드하고 싶지 않았습니다.