'diff'(또는 기타)를 사용하여 텍스트 파일 간의 문자 수준 차이 가져 오기


91

나는 'diff'를 사용하여 문자 차이와 문자 차이를 모두 얻고 싶습니다. 예를 들어 다음을 고려하십시오.

파일 1

abcde
abc
abcccd

파일 2

abcde
ab
abccc

diff -u 사용 하면 다음을 얻습니다.

@@ -1,3 +1,3 @@
 abcde
-abc
-abcccd
\ No newline at end of file
+ab
+abccc
\ No newline at end of file

그러나 그것은 이러한 라인의 변화만을 보여줍니다. 내가보고 싶은 것은 다음과 같습니다.

@@ -1,3 +1,3 @@
 abcde
-ab<ins>c</ins>
-abccc<ins>d</ins>
\ No newline at end of file
+ab
+abccc
\ No newline at end of file

당신은 내 표류를 얻습니다.

이제 다른 엔진 을 사용 하여 특정 라인의 차이를 표시 / 확인할 수 있다는 것을 알고 있습니다 . 하지만 차라리 모든 작업을 수행하는 하나의 도구를 사용하고 싶습니다.


2
per char diff는 단어 분할을 위해 공백이 적용되지 않는 CJK 텍스트와 관련하여 특히 유용합니다.
把友情留在无盐

답변:


75

Git에는 diff라는 단어가 있으며 모든 문자를 단어로 정의하면 효과적으로 문자 차이를 얻을 수 있습니다. 그러나 개행 변경은 무시 됩니다.

다음과 같은 저장소를 만듭니다.

mkdir chardifftest
cd chardifftest
git init
echo -e 'foobarbaz\ncatdog\nfox' > file
git add -A; git commit -m 1
echo -e 'fuobArbas\ncat\ndogfox' > file
git add -A; git commit -m 2

이제 수행 git diff --word-diff=color --word-diff-regex=. master^ master하면 다음을 얻을 수 있습니다.

git diff

추가 및 삭제 모두 문자 수준에서 인식되는 반면 개행 문자의 추가 및 삭제는 모두 무시됩니다.

다음 중 하나를 시도해 볼 수도 있습니다.

git diff --word-diff=plain --word-diff-regex=. master^ master
git diff --word-diff=porcelain --word-diff-regex=. master^ master

76
리포지토리를 전혀 만들 필요가 없습니다. 파일 시스템의 어느 곳에서나 git diff 파일 두 개를 제공하면 작동합니다. 당신의 명령은 그런 식으로 저에게 잘 작동합니다. 감사합니다! git diff --word-diff=color --word-diff-regex=. file1 file2
qwertzguy

1
이것은 매우 도움이됩니다! 내가 할 수 있다면 소프트웨어 개발자로서 한 번 +1하고 저자 / 작가로서 두 배 더 많이 +1 할 것입니다. 줄이 합리적으로 짧아지는 코드와는 달리 논문 / 이야기를 작성할 때 각 단락은 긴 단어 줄 바꿈 형식을 취하는 경향이 있으며이 기능은 diff를 실제로 시각적으로 유용하게 만듭니다.
mtraceur

29
--no-indexgit repo 외부에서 나를 위해 작동하도록하기 위해 위의 to @ qwertzguys의 응답 을 추가 해야했습니다. 그래서 :git diff --no-index --word-diff=color --word-diff-regex=. file1 file2
Nathan Bell

2
git diff는 일반 설정에서 작동하지 않습니다 : git diff --no-index --word-diff = color --word-diff-regex =. <(echo string1) <(echo string2) .. 아무것도 아니지만 작동합니다 : diff --color <(echo string1) <(echo string2).
mosh

1
@NathanBell 내가 추가 할 필요가 --no-index너무 REPO의 내부
JShorthouse

32

당신이 사용할 수있는:

diff -u f1 f2 |colordiff |diff-highlight

스크린 샷

colordiffUbuntu 패키지입니다. 을 사용하여 설치할 수 있습니다 sudo apt-get install colordiff.

diff-highlightgit에서 가져온 것입니다 (버전 2.9부터). 에 있습니다 /usr/share/doc/git/contrib/diff-highlight/diff-highlight. 당신은 당신의 $PATH.


6
colordiff는 Mac 용 homebrew에서도 사용할 수 있습니다.brew install colordiff
Emil Stenström 19 년

5
Mac diff-highlight에서 찾을 수 있습니다$(brew --prefix git)/share/git-core/contrib/diff-highlight/diff-highlight
StefanoP 2019 년

2
brew를 사용하여 git을 설치하지 않은 경우 diff-highlight-python의 pip로도 설치할 수 있습니다.- pip install diff-highlight(git이 brew를 통해 설치 되더라도 선호합니다)
Yaron U.

22

프로그래밍 방식으로이 작업을 수행하려면 Python의 difflib 가 ace입니다. 대화식 사용을 위해 저는 vim의 diff 모드를 사용합니다 (사용하기에 충분히 쉬움 :으로 vim 호출 vimdiff a b). 나는 또한 간혹 Beyond Compare를 사용하는데 , 이것은 diff 도구에서 기대할 수있는 거의 모든 것을 수행합니다.

이 작업을 유용하게 수행하는 명령 줄 도구는 없지만 Will이 언급했듯이 difflib 예제 코드가 도움이 될 수 있습니다.


1
오 .. 나는 좀 더 표준화 된 것을 바라고 있었다 (숨겨진 명령 줄 인수와 같은). 가장 나쁜 점은 Beyond Compare 2가 있고 diff의 파일 / 콘솔에 대한 텍스트 출력도 지원하지만 여전히 char-diff가 아닌 line-diff 만 포함한다는 것입니다. 아무도 없다면 파이썬을 살펴 보겠습니다.
VitalyB

6
나를 vimdiff에 소개하는 +1. 기본 색상은 읽을 수 없지만 stackoverflow.com/questions/2019281/… 에서 해결책을 찾았습니다 .
정의되지 않은

18

cmpSolaris에서 다음 명령을 사용할 수 있습니다 .

cmp

두 파일을 비교하고 다른 경우 첫 번째 바이트와 행 번호가 다른 부분을 알려줍니다.


2
cmp(적어도 일부) Linux 배포판에서도 사용할 수 있습니다.
Jeff Evans

7
Mac OS X에서도 사용할 수 있습니다.
Eric R. Rath

문자는 여러 바이트로 구성 될 수 있으며 OP는 시각적 비교를 요청합니다.
Cees Timmerman

1
@CeesTimmerman : cmp는 flag를 사용하여 시각적 비교를 허용 -l -b합니다.
Smar

10

Python에는 difflib질문에 답하는 데 도움이 될 수있는 편리한 라이브러리 가 있습니다.

다음은 difflib다른 파이썬 버전에 사용하는 두 개의 oneliner 입니다.

python3 -c 'import difflib, sys; \
  print("".join( \
    difflib.ndiff( \ 
      open(sys.argv[1]).readlines(),open(sys.argv[2]).readlines())))'
python2 -c 'import difflib, sys; \
  print "".join( \
    difflib.ndiff( \
      open(sys.argv[1]).readlines(), open(sys.argv[2]).readlines()))'

이것들은 .NET으로 이동하기 쉬운 쉘 별칭으로 유용 할 수 있습니다 .${SHELL_NAME}rc.

$ alias char_diff="python2 -c 'import difflib, sys; print \"\".join(difflib.ndiff(open(sys.argv[1]).readlines(), open(sys.argv[2]).readlines()))'"
$ char_diff old_file new_file

그리고 더 읽기 쉬운 버전으로 독립형 파일에 넣습니다.

#!/usr/bin/env python2
from __future__ import with_statement

import difflib
import sys

with open(sys.argv[1]) as old_f, open(sys.argv[2]) as new_f:
    old_lines, new_lines = old_f.readlines(), new_f.readlines()
diff = difflib.ndiff(old_lines, new_lines)
print ''.join(diff)

우수한 한 라이너. 변경되지 않은 라인을 무시하는 압축 된 출력을 갖는 것이 좋을 것입니다.
aidan.plenert.macdonald

6
cmp -l file1 file2 | wc

나를 위해 잘 작동했습니다. 결과의 가장 왼쪽 숫자는 다른 문자 수를 나타냅니다.


1
또는 cmp -l file1 file2 | wc -l
Tony

5

또한 Longest 공통 하위 시퀀스 알고리즘을 사용하여이 문제를 해결하기 위해 자체 스크립트작성 했습니다 .

그렇게 실행됩니다.

JLDiff.py a.txt b.txt out.html

결과는 빨간색과 녹색 색상의 html입니다. 더 큰 파일은 처리하는 데 기하 급수적으로 더 많은 시간이 걸리지 만 이것은 먼저 한 줄씩 확인하지 않고 문자별로 진정한 문자 비교를 수행합니다.


JLDiff가 pypy에서 훨씬 빠르게 실행된다는 것을 발견했습니다.
Joshua

4

컬러, 문자 수준 diff 출력

아래 스크립트와 diff-highlight (git의 일부)로 할 수있는 작업은 다음과 같습니다 .

컬러 차이 스크린 샷

#!/bin/sh -eu

# Use diff-highlight to show word-level differences

diff -U3 --minimal "$@" |
  sed 's/^-/\x1b[1;31m-/;s/^+/\x1b[1;32m+/;s/^@/\x1b[1;34m@/;s/$/\x1b[0m/' |
  diff-highlight

( 강조 표시에 대한 @retracile의 답변에 대한 크레딧 sed)


쉘 화면에서 좋은 diff를 보여 주지만 GVim에서 어떻게 그 차이를 볼 수 있습니까 ??
Hemant Sharma

1
정말 gvim 질문입니다 :). command | gvim -당신이 원하는 것을 할 것입니다.
Att Righ

참고로 diff-highlight는 git경로의 일부로 포함 되지만 경로에 배치되지 않은 것으로 보입니다 . 내 컴퓨터 하나는 /usr/share/doc/git/contrib/diff-highlight.
Att Righ

끊어진 링크. diff-highlight를 어떻게 설치합니까? 패키지 관리자에없는 것 같습니다.
Trevor Hickey

3

파이썬의 difflib는 이것을 할 수 있습니다.

설명서에는 사용자를위한 예제 명령 줄 프로그램이 포함 되어 있습니다.

정확한 형식은 지정한 형식이 아니지만 ndiff 스타일 출력을 구문 분석하거나 예제 프로그램을 수정하여 표기법을 생성하는 것은 간단합니다.


감사! 조사하겠습니다. 나는 더 표준화 된 무언가를 원했다 (숨겨진 명령 줄 인수와 같은). 하지만 여전히 괜찮을 수 있습니다. 아무도 더 표준이 없다면 파이썬을 살펴볼 것입니다.
VitalyB

2

다음은 온라인 텍스트 비교 도구입니다. http://text-compare.com/

다른 모든 문자를 강조 표시하고 나머지를 계속 비교할 수 있습니다.


이것은 단일 문자에 대한 옵션이없는 라인 레벨 diff를 수행하는 것으로 보입니다. 캐릭터를 비교하기 위해 어떻게 얻습니까?
Dragon

아, 다른 캐릭터를 강조합니다. 그러나 그것은 여전히 ​​라인 레벨 catdog이고 cat\ndog오직 일치 할 것입니다cat
Dragon

1

저는 더 간단한 해결책이 항상 좋은 해결책이라고 생각합니다. 제 경우에는 아래 코드가 많은 도움이됩니다. 다른 사람에게 도움이되기를 바랍니다.

#!/bin/env python

def readfile( fileName ):
    f = open( fileName )
    c = f.read()
    f.close()
    return c

def diff( s1, s2 ):
    counter=0
    for ch1, ch2 in zip( s1, s2 ):
        if not ch1 == ch2:
            break
        counter+=1
    return counter < len( s1 ) and counter or -1

import sys

f1 = readfile( sys.argv[1] )
f2 = readfile( sys.argv[2] )
pos = diff( f1, f2 )
end = pos+200

if pos >= 0:
    print "Different at:", pos
    print ">", f1[pos:end]
    print "<", f2[pos:end]

선호하는 터미널에서 다음 구문으로 두 파일을 비교할 수 있습니다.

$ ./diff.py fileNumber1 fileNumber2


0

완전한 대답은 아니지만 cmp -l의 출력이 충분히 명확하지 않은 경우 다음을 사용할 수 있습니다.

sed 's/\(.\)/\1\n/g' file1 > file1.vertical
sed 's/\(.\)/\1\n/g' file2 > file2.vertical
diff file1.vertical file2.vertical

OSX에서는```sed 's / (.) / \ 1 \'$ '\ n / g'file1> file1.vertical sed 's / \ (. \) / \ 1 \'$ '\ n / g를 사용합니다. '파일 2> file2.vertical```
mmacvicar

0

이 답변의 대부분은 Perl 모듈 인 diff-highlight 사용을 언급 합니다. 하지만 Perl 모듈을 설치하는 방법을 알고 싶지 않았습니다. 그래서 필자는 자체 포함 된 Perl 스크립트가되도록 약간 변경했습니다.

다음을 사용하여 설치할 수 있습니다.

▶ curl -o /usr/local/bin/DiffHighlight.pl \
   https://raw.githubusercontent.com/alexharv074/scripts/master/DiffHighlight.pl

그리고 사용법 ( colordiffzhanxw의 답변에 우분투가 언급 된 경우 ) :

▶ diff -u f1 f2 | colordiff | DiffHighlight.pl

그리고 사용법 (그렇지 않은 경우) :

▶ diff -u f1 f2 | DiffHighlight.pl
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.