라인 내에서 차이


113

차이점을보고있는 SQL 덤프가 있습니다. diff분명히 두 줄의 차이점을 보여줄 수는 있지만 쉼표로 구분 된 긴 목록의 값 중 실제로 줄을 다르게 만드는 값을 찾으려고 노력하고 있습니다.

특정 파일에서 두 줄의 정확한 문자 차이를 지적하기 위해 어떤 도구를 사용할 수 있습니까?


답변:


93

wdiff 가 있습니다 .

데스크탑에서 meld 는 한 줄의 차이점을 강조 표시 할 수 있습니다.


8
컬러 wdiff :wdiff -w "$(tput bold;tput setaf 1)" -x "$(tput sgr0)" -y "$(tput bold;tput setaf 2)" -z "$(tput sgr0)" file1 file2
l0b0

47
색상의 경우 colordiff를 설치 한 후 다음을 수행하십시오.wdiff a b | colordiff
philfreo

실제로 Meld는 라인 기반 파일 간의 인라인 차이를 표시하는 데 매우 느립니다 (분) .
Dan Dascalescu

이 또한 dwdiff과 대부분 호환 도구 wdiff뿐만 아니라 색깔의 출력과 아마 몇 가지 다른 기능을 지원합니다. 그리고 Arch와 같은 일부 Linux 배포판에서 더 많이 사용할 수 있습니다.
MarSoft

4
wdiff -n a b | colordiff, 조언합니다 man colordiff.
Camille Goudeseune

25

git-diff를 사용하는 또 다른 방법 :

git diff -U0 --word-diff --no-index -- foo bar | grep -v ^@@

diff의 위치에 관심이 없다면 grep -v.


2
이것은 내가 모방하려고하는 행동입니다. 파일 중 하나를 색인화하지 않고 git-diff를 사용할 수 있다는 것을 알지 못했습니다.
spinup

1
여기서 --word-diff가 핵심 옵션입니다. 감사!
user2707671

1
--no-index는 git 작업 디렉토리에 있고 foo와 bar가 모두 필요한 경우에만 필요합니다.
xn.

22

나는 이것을 위해 사용 vimdiff했다.

여기에 눈에 띄지 않는 스크린 샷이 있습니다. 너무 빠른 튜토리얼 .


차이를 발견하지 못했습니다 내 경우에는 너무 특정 긴 줄이 모두 있었다 gvim을 -d F1 F2의 파일 그러나 실제 차이가 추가 빨간색으로 강조되었다 다른 것으로 강조 오픈
zzapper

나는 vim을 영원히 사용했지만 vimdiff에 대해서는 전혀 몰랐다!
mitchus

그리고 문자 수준의 diff 에는 diffchar.vim 이 있습니다.

2
vim과 vimdiff를 좋아하는 한 줄에서 차이점을 강조 표시하는 vimdiff의 알고리즘은 매우 기본적입니다. 일반적인 접두사와 접미사를 제거하고 서로 다른 것을 강조 표시하는 것 같습니다. 변경된 모든 문자가 함께 그룹화되어 있으면 작동하지만, 퍼져 있으면 제대로 작동하지 않습니다. 단어 줄 바꿈 텍스트에는 끔찍합니다.
Laurence Gonsalves

OP에서와 같이 긴 줄의 경우 stackoverflow.com/a/45333535/2097284를vimdiff -c 'set wrap' -c 'wincmd w' -c 'set wrap' a b 제안 합니다.
Camille Goudeseune 17

6

여기에 ... 방법은 "당신을 비트 개의 ..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
#

4

wdiff실제로 파일을 단어 단위로 비교하는 매우 오래된 방법입니다. 파일을 다시 포맷 한 다음 diff차이점을 찾아 다시 전달 하여 사용 했습니다. 나는 단어별로 비교하는 대신 컨텍스트를 추가하여 다른 '컨텍스트'단어로 둘러싸인 각 단어와 함께 수행하도록 제안했습니다. 따라서 파일의 공통된 구절에서 diff가 훨씬 더 잘 동기화됩니다. 특히 파일이 몇 개의 공통 단어 블록으로 대부분 다른 경우. 예를 들어 표절이나 재사용을 위해 텍스트를 비교할 때.

dwdiff나중에에서 만들었습니다 wdiff. 그러나 dwdiff 텍스트 재 포맷 기능을 사용하여에 효과적입니다 dwfilter. 이것은 대단한 발전입니다. 즉, 한 텍스트를 다른 텍스트와 일치하도록 다시 포맷 한 다음 라인 별 그래픽 차이 표시기를 사용하여 비교할 수 있습니다. 예를 들어, "확산"그래픽 diff ....와 함께 사용

dwfilter file1 file2 diffuse -w

이것은 형식 file1을 재 형식화 하고 시각적 비교 file2diffuse위해 제공합니다 . file2은 수정되지 않았으므로에서 단어 차이를 직접 편집하여 단어 차이를 병합 할 수 있습니다 diffuse. 편집하려는 경우 다시 포맷 할 파일을 역으로 file1추가 할 수 있습니다 -r. 그것을 시도하고 당신은 그것이 매우 강력하다는 것을 알게 될 것입니다!

그래픽 diff (위 그림 참조)에 대한 나의 선호 diffuse는 훨씬 깨끗하고 유용하다고 느끼는 것입니다. 또한 독립형 파이썬 프로그램이므로 다른 UNIX 시스템에 쉽게 설치하고 배포 할 수 있습니다.

다른 그래픽 차이에는 많은 의존성이있는 것처럼 보이지만 사용할 수도 있습니다 (선택). 여기에는 kdiff3또는 이 포함됩니다 xxdiff.


4

@ 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

3

간단한 원 라이너는 다음과 같습니다.

diff -y <(cat a.txt | sed -e 's/,/\n/g') <(cat b.txt | sed -e 's/,/\n/g')

아이디어는을 사용하여 쉼표 (또는 사용하려는 구분 기호)를 줄 바꿈으로 바꾸는 것 sed입니다. diff그런 다음 나머지를 처리합니다.


2
  • xxdiff : 다른 도구는 xxdiff (GUI)이며, 먼저 설치해야합니다.
  • 스프레드 시트 : 데이터베이스 데이터의 경우 스프레드 시트를 .csv쉽게 만들 수 있으며 수식 (A7==K7) ? "" : "diff"또는 이와 유사한 것을 삽입하여 복사하여 붙여 넣을 수 있습니다.

1
xxdiff는 80 년대처럼 보입니다. Meld는 훨씬 좋아 보이지만 CSV와 같은 파일의 경우 속도가 매우 느립니다. Diffuse 가 가장 빠른 Linux diff 도구라는 것을 알았습니다 .
Dan Dascalescu

@ DanDascalescu : 작업을 수행하는 도구는 모양에 관계없이 항상 멋지게 보입니다. 또 다른 하나는 가끔 사용했지만 긴 열 데이터로 테스트하기 위해 설치되지 않은 tkdiff 입니다.
사용자 알 수 없음

xxdiff 는 이동 한 행을 표시합니까 ? 아니면 한 파일에 누락 된 줄이 표시되고 다른 파일에 추가 된 줄만 표시됩니까? (xxdiff 빌드를 시도했지만 qmake가 실패했으며 데비안 패키지를 게시하지 않아도됩니다).
Dan Dascalescu

@ DanDascalescu : 오늘은 tkdiff 만 설치했습니다.
사용자 알 수 없음

1

커맨드 라인에서 파일을 비교하기 전에 적절한 줄 바꿈을 추가해야합니다. sed, awk, perl 등을 사용하여 체계적인 방식으로 줄 바꿈을 추가 할 수 있습니다. 너무 많이 추가하지 마십시오.

그러나 단어 차이를 강조 표시하는 vim을 사용하는 것이 가장 좋습니다. 차이가 너무 많지 않고 단순하면 vim이 좋습니다.


실제로이 질문에 대한 답은 아니지만이 기술은 긴 줄의 작은 차이에 대해 배우는 데 효과적입니다.
jknappen 2019

1

kdiff3 는 Linux에서 표준 GUI diff 뷰어가되고 있습니다. xxdiff 와 비슷 하지만 kdiff3이 더 좋다고 생각합니다. "특정 파일에서 두 줄의 정확한 문자 차이"를 표시하라는 요청을 포함하여 많은 일을 잘 수행합니다.


KDiff3는 CSV 파일에서 인라인 차이를 강조하는 데 매우 느립니다 . 나는 그것을 추천하지 않을 것입니다.
Dan Dascalescu

1

귀하의 질문을 올바르게 읽으면 diff -y이런 종류의 것을 사용합니다.

차이를 던지는 행을 찾기 위해 병렬 비교를 훨씬 간단하게 만듭니다.


1
이것은 라인 내의 차이점을 강조하지 않습니다. 줄이 길면 차이를 보는 것이 고통 스럽습니다. wdiff, git diff --word-diff, vimgit, meld, kbdiff3, tkdiff 모두이 작업을 수행합니다.
user2707671

1

나는 같은 문제가 있었고 세분성을 지정할 수있는 온라인 도구 인 PHP Fine Diff로 해결했습니다 . 나는 그것이 기술적으로 * nix 도구가 아니라는 것을 알고 있지만, 한 번만 문자 수준 diff를하기 위해 프로그램을 다운로드하고 싶지 않았습니다.


일부 사용자는 중요하거나 큰 파일을 임의의 온라인 도구에 업로드 할 수 없습니다. 있습니다 라인 레벨의 차이를 보여 도구의 많은 개인 정보를 손상시키지 않고는.
Dan Dascalescu

네, 있습니다. 그러나 민감한 정보가 포함되지 않은 diff의 경우 온라인 도구가 좋은 솔루션이 될 수 있습니다.
pillravi

온라인 diff 도구는 명령 줄 통합도 지원하지 않습니다. 버전 관리 흐름에서는 사용할 수 없습니다. 또한 사용하기가 훨씬 번거롭고 (파일 1 선택, 파일 2 선택, 업로드) 병합 할 수 없습니다.
Dan Dascalescu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.