두 파일을 한 줄씩 비교하고 다른 파일에서 차이 생성


121

file1을 file2와 비교하고 file2에없는 file1의 줄을 포함하는 file3을 생성하고 싶습니다.


diff를 시도했지만 다른 줄 앞에 숫자와 다른 기호가 생성되어 파일을 비교하기가 어렵습니다.
Sun

답변:


216

diff (1)은 답이 아니지만 comm (1)은 답입니다.

NAME
       comm - compare two sorted files line by line

SYNOPSIS
       comm [OPTION]... FILE1 FILE2

...

       -1     suppress lines unique to FILE1

       -2     suppress lines unique to FILE2

       -3     suppress lines that appear in both files

그래서

comm -2 -3 file1 file2 > file3

입력 파일을 정렬해야합니다. 그렇지 않은 경우 먼저 정렬하십시오. 이것은 임시 파일로 할 수 있습니다.

comm -2 -3 <(sort file1) <(sort file2) > file3

쉘이 프로세스 대체를 지원하는 경우 (bash는 지원함).


1
두 파일은 정렬되어야하며 고유해야합니다
andy

6
옵션을 함께 그룹화 할 수 있습니다.comm -23
Paolo M

"정렬"은 무엇을 의미합니까? 라인의 순서가 같습니까? 그런 다음 백업 된 이전 버전과 비교하여 추가 된 행을 확인하는 것과 같이 대부분의 사용 사례에서 괜찮을 것입니다. 새로 추가 된 줄이 기존 줄 사이에있을 수없는 경우 문제가 더 많습니다.
Egor Hans

@EgorHans : 예를 들어 파일에 "3 \ n1 \ n3 \ n2 \ n"과 같은 정수가 포함 된 줄이있는 경우 줄은 먼저 오름차순 또는 내림차순으로 다시 정렬해야합니다 (예 : "\ 1 \ n2 \ n3 \ n3 \ n"). 인접. 이는 "정렬"되며 두 파일 모두 유사한 방식으로 정렬되어야합니다. 최신 파일에 새 줄이있는 경우 "기존 줄 사이"에 있는지 여부는 중요하지 않습니다. 정렬 후에는 정렬 된 순서에 있기 때문입니다.
sorpigal

48

Unix 유틸리티 diff는 정확히이 목적을위한 것입니다.

$ diff -u file1 file2 > file3

옵션, 다른 출력 형식 등은 설명서와 인터넷을 참조하십시오.


8
그것은 요청한 작업을 수행하지 않습니다. 다른 답변에서 제안 된 명령 줄 스위치를 사용하더라도 많은 추가 문자를 삽입합니다.
xenocyon

20

이것을 고려하십시오 :
파일 a.txt :

abcd
efgh

b.txt 파일 :

abcd

다음과 같은 차이점을 찾을 수 있습니다.

diff -a --suppress-common-lines -y a.txt b.txt

출력은 다음과 같습니다.

efgh 

다음을 사용하여 출력 파일 (c.txt)의 출력을 다시 추출 할 수 있습니다.

diff -a --suppress-common-lines -y a.txt b.txt > c.txt

이것은 귀하의 질문에 답할 것입니다.

"... file2에없는 file1의 행을 포함합니다."


2
이 답변에는 두 가지 제한이 있습니다. (1) 짧은 줄 (기본적으로 80 자 미만이지만 수정할 수 있음)에서만 작동하며 더 중요한 것은 (2) 각 끝에 "<"를 추가합니다. 다른 프로그램 (예 : awk, sed)과 함께 제거해야하는 줄.
sergut 2015

대부분의 경우 가능한 가장 작은 diff를 찾기 위해 최선을 다하는를 사용하고 싶을 -ddiff입니다. -i, -E, -w, -B--suppress-blank-empty도 있지만 항상 그렇지는 때때로 유용 할 수 있습니다. 사용 사례에 맞는 것이 무엇인지 모르겠다면 diff --help먼저 시도해보십시오 (일반적으로 명령이 무엇을 할 수 있는지 모를 때 좋은 생각입니다).
Egor Hans

또한 --line-format = % L을 사용하면 diff가 추가 문자를 생성하는 것을 방지 할 수 있습니다 (적어도 도움말은 이렇게 작동한다고 말하지만 시도해 볼 것입니다).
Egor Hans

또한이 짧고 동일하게 작동 보인다 stackoverflow.com/a/27667185/1179925을
mrgloom

8

때로는 diff필요한 유틸리티이지만 때로는 join더 적절합니다. 파일은 미리 정렬되어야하며 bash, ksh 또는 zsh와 같은 프로세스 대체를 지원하는 쉘을 사용하는 경우 즉시 정렬을 수행 할 수 있습니다.

join -v 1 <(sort file1) <(sort file2)

이것에 대한 메달을 받아야합니다! 지난 2 시간 동안 정확히 제가 찾고 있던 것이 었습니다
Zatarra

7

시험

sdiff file1 file2

일반적으로 대부분의 경우 훨씬 더 잘 작동합니다. 줄 순서가 중요하지 않은 경우 (예 : 일부 텍스트 구성 파일) 파일을 먼저 정렬 할 수 있습니다.

예를 들면

sdiff -w 185 file1.cfg file2.cfg

1
좋은 유틸리티! 나는 그것이 차별화 라인을 표시하는 방법을 좋아합니다. 구성을 훨씬 쉽게 비교할 수 있습니다. 종류와이 함께 치명적인 콤보 (예 sdiff <(sort file1) <(sort file2))
jmagnusson

3

coreutils로이 문제를 해결해야하는 경우 허용되는 답변이 좋습니다.

comm -23 <(sort file1) <(sort file2) > file3

정렬이나 처리 대체가 필요하지 않고 무한 스트림을 지원 하는 sd (stream diff) 도 사용할 수 있습니다 .

cat file1 | sd 'cat file2' > file3

아마도이 예에서 그다지 많은 이점은 아니지만 여전히 고려하십시오. 어떤 경우에는 comm또는 을 사용할 수 grep -F없습니다 diff.

여기에 sd를 소개하는 터미널의 diffing stream에 대해 쓴 블로그 포스트가 있습니다.


3

그러나 grep해결책이 없습니까?

  • file2에만있는 행 :

    grep -Fxvf file1 file2 > file3
  • file1에만있는 행 :

    grep -Fxvf file2 file1 > file3
  • 두 파일에 모두있는 줄 :

    grep -Fxf file1 file2 > file3

2

이미 많은 답변이 있지만 완벽한 IMHO는 없습니다. Thanatos의 대답은 한 줄에 추가 문자를 남기고 Sorpigal의 대답은 파일을 정렬하거나 미리 정렬해야하므로 모든 상황에서 적절하지 않을 수 있습니다.

나는 다른 아무것도 다른 (여분의 문자, 아니 재정렬)없는 라인을 얻을 수있는 가장 좋은 방법의 조합이라고 생각 diff, grep그리고 awk(또는 유사).

행에 "<"가 포함되지 않은 경우 짧은 한 줄은 다음과 같습니다.

diff urls.txt* | grep "<" | sed 's/< //g'

그러나 이것은 줄에서 "<"(보다 작음, 공백)의 모든 인스턴스를 제거합니다. 항상 괜찮은 것은 아닙니다 (예 : 소스 코드). 가장 안전한 옵션은 awk를 사용하는 것입니다.

diff urls.txt* | grep "<" | awk '{for (i=2; i<NF; i++) printf $i " "; print $NF}'

이 한 줄짜리 파일은 두 파일을 비교 한 다음 diff의 ed 스타일 출력을 필터링 한 다음 diff가 추가하는 후행 "<"를 제거합니다. 줄에 "<"자체가 포함되어 있어도 작동합니다.


1
comm은 정렬이 필요하지 않습니다 (최신 버전에서는?)---nocheck-order를 사용하십시오. CLI에서 csv를 조작 할 때 많이 사용합니다
ak5

2

예를 들어, 나란히 출력diff -y생성한다고 언급 한 사람이 아무도 없다는 것에 놀랐습니다 .

diff -y file1 file2 > file3

그리고 file3(다른 줄에는 |중간에 기호 가 있음) :

same     same
diff_1 | diff_2

1

Diff 유틸리티를 사용하고 출력에서 ​​<로 시작하는 행만 추출하십시오.


0
diff a1.txt a2.txt | grep '> ' | sed 's/> //' > a3.txt

이 스레드에서 거의 모든 답변을 시도했지만 완료되지 않았습니다. 하나 위의 몇 가지 흔적이 나를 위해 일했습니다. diff 는 당신에게 차이 를 줄 것이지만 원치 않는 특별한 캐릭터가 있습니다. 실제 차이 라인은 '>'로 시작합니다. 그래서 다음 단계는 grep 라인이 '>'로 시작하고 sed로 동일한 것을 제거하는 것 입니다.


1
이것은 나쁜 생각입니다. 로 시작하는 줄도 수정해야합니다 <. 입력 파일의 순서를 바꾸면 이것을 볼 수 있습니다. 이 작업을 수행하더라도 grepmore sed를 사용하여 생략 할 수 있습니다 .`diff a1 a2 | SED '/> / S ///' '이 여전히 포함 라인 깰 수 >또는 <권리 상황과 여전히 줄 번호를 설명하는 추가 라인을 떠난다. 이 접근법을 시도하고 싶다면 더 나은 방법은 다음과 같습니다 diff -C0 a1 a2 | sed -ne '/^[+-] /s/^..//p'.
sorpigal

0

diff다음 출력 형식과 함께 사용할 수 있습니다 .

diff --old-line-format='' --unchanged-line-format='' file1 file2

--old-line-format='', file2에서 줄이 다른 경우 file1에 대한 출력을 비활성화합니다.
--unchanged-line-format='', 행이 같으면 출력을 비활성화합니다.

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