한 파일에서 다른 파일에없는 행을 가져 오는 도구가 있습니까?


110

파일 A에 포함 된 줄을 얻을 수 있지만 파일 B에는없는 줄을 얻을 수있는 도구가 있습니까? 예를 들어 perl을 사용하여 약간의 간단한 스크립트를 만들 수 있지만, 이와 같은 것이 이미 존재하면 지금부터 시간을 절약 할 수 있습니다.



답변:


159

예. grep텍스트 문자열에 대한 파일 검색을위한 표준 도구를 사용하여 한 파일의 모든 줄을 다른 파일에서 뺄 수 있습니다.

grep -F -x -v -f fileB fileA

이것은 fileB의 각 행을 패턴 ( -f fileB)으로 사용하고 일반 정규식이 아닌 일반 문자열로 처리하여 작동합니다 ( -F). 전체 줄 ( -x) 에서 일치하도록 강제하고 일치 하지 않는 줄 ( ) 만 인쇄합니다 -v. 따라서 fileB의 행과 동일한 데이터를 포함하지 않는 fileA의 행을 인쇄합니다.

이 솔루션의 단점은 라인 순서를 고려하지 않으며 입력에 다른 위치에 중복 라인이 있으면 예상 한 것을 얻지 못할 수 있다는 것입니다. 이에 대한 해결책은과 같은 실제 비교 도구를 사용하는 것 diff입니다. 파일에서 행의 100 %에 컨텍스트 값으로 diff 파일을 작성한 다음 파일 A를 파일 B로 변환 할 때 제거 될 행에 대해 구문 분석하여이를 수행 할 수 있습니다 (이 명령은 diff도 제거합니다) 올바른 줄을 얻은 후 서식을 지정하십시오.)

diff -U $(wc -l < fileA) fileA fileB | sed -n 's/^-//p' > fileC

@ inderpreet99 소문자 -u인수는 공백이 없는 한 실제로는 숫자의 매개 변수를 사용합니다. 이전에 사용했던 방식의 장점은 값과 함께 또는 값없이 작동하므로 출력되지 않은 리턴 된 하위 명령 루틴에서 무언가를 사용할 수 있다는 것입니다. 반면 대문자 '-U'는 인수가 필요합니다.
Caleb

grep -f is O (N ^ 2)주의하십시오 : stackoverflow.com/questions/4780203/…
rogerdpack

1
diff파이프 라인은 치료 덕분에 작동합니다.
Felipe Alvarez

정렬 문제를 설명하기 위해 명령에서 프로세스 대체 를 사용 하여 grep필요에 따라 각 파일을 처리 할 수 있습니다 . 예 :grep -F -x -v -f <(sort fileB) <(sort fileA)
Tony Cesaro

@TonyCesaro 데이터 세트가 주문별로 다르고 복제본을 고려할 필요가없는 경우 작동합니다. 사용의 장점은 diff파일의 위치가 고려된다는 것입니다.
Caleb

57

대답은 비교할 파일의 형식과 형식에 따라 다릅니다.

비교중인 파일이 정렬 된 텍스트 파일 인 경우 Richard Stallman과 Davide McKenzie가 작성한 GNU 도구가 comm사용자가 수행 한 필터링을 수행 할 수 있습니다. coreutils의 일부입니다.

다음 2 개의 파일이 있다고 가정하십시오.

$ cat a
1
2
3
4
5

$ cat b
1
2
3
4
5
6

파일 b에없는 파일의 행 a:

$ comm <(sort a) <(sort b) -3
    6

1
언급 +1 comm; 불행히도, comm정렬 된 파일이 필요합니다
Arcege

11
그래서 그들을 정렬? comm <(정렬 a) <(정렬 b)
-1-2

이것은 이상한 구문입니다. <()? 그것은 효과가 있고 그것을 얻지만이 이상한 이름이 있습니까?
mlissner

2
@mlissner <()프로세스 대체 라고도 합니다.
miku

1
comm원래는 1973 년경 RMS가 아닌 Bell Labs의 누군가에 의해 작성되었습니다. 나중에 많은 GNU 구현을 언급하고 있습니다. 수년에 걸쳐 유닉스 유틸리티의 많은 구현이 있었다.
Stéphane Chazelas

32

에서 유래 ...

통신 -23 file1 file2

-23은 두 파일 또는 파일 2에만있는 행을 표시하지 않습니다. 파일을 정렬해야하지만 (예제에서는) 정렬되지 않은 경우 먼저 정렬을 통해 파이프하십시오.

맨 페이지 참조


이것은 어떤 이유로 든 나를 위해 작동하지 않습니다 ...
Jan

@Jan 파일이 정렬되어 있습니까? 어떻게 정렬 했습니까?
JJS

8

grep 및 comm (정렬) 방법은 큰 파일에서 시간 이 오래 걸립니다. SiegeX와 ghostdog74 는 Stack Overflow에서 두 파일 중 하나에 고유 한 행을 추출하는 두 가지 훌륭한 방법을 공유했습니다 .

$ awk 'FNR==NR{a[$0]++}FNR!=NR && !a[$0]{print}' file1 file2

$ awk 'FNR==NR{a[$0]++;next}(!($0 in a))' file1 file2

2
거대한 파일을 사용 하여이 작업을 수행하면 대용량 파일을 연관 배열에로드하는 메모리 제약이 엄청납니다.
Charles Duffy

4

파일이 크고 입력에 대한 사용자 정의 순서가 없으면 grep이 너무 오래 걸립니다. 빠른 대안은

sort file1 > 1 
sort file2 > 2 
diff 1 2 | grep "\>" | sed -e 's/> //'

[file2-file1 결과는 화면으로, 파이프는 파일로 등]

변경 >하려면 <반대 빼기를 얻을 것입니다.rm 1 2


2

vimdiff를 고려할 수도 있습니다. vim 편집기에서 파일 간의 차이점을 강조 표시합니다.


1
그러나 Vimdiff에서 자동으로 빼기를 수행하는 쉬운 방법이 있습니까?
Kazark
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.