두 개의 큰 파일의 차이점


14

"test1.csv"가 포함되어 있으며

200,400,600,800
100,300,500,700
50,25,125,310

test2.csv 및 포함

100,4,2,1,7
200,400,600,800
21,22,23,24,25
50,25,125,310
50,25,700,5

지금

diff test2.csv test1.csv > result.csv

~와 다르다

diff test1.csv test2.csv > result.csv

올바른 순서가 무엇인지 모르지만 다른 것을 원합니다. 위의 두 명령 모두 다음과 같은 결과를 출력합니다.

2 > 100,4,2,1,7
   3 2,3c3,5
   4 < 100,300,500,700
   5 < 50,25,125,310
   6 \ No newline at end of file
   7 ---
   8 > 21,22,23,24,25
   9 > 50,25,125,310

차이점 만 출력하고 싶기 때문에 results.csv는 다음과 같아야합니다.

100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5

나는 시도 diff -q하고 diff -s있지만 트릭을하지 않았다. 순서는 중요하지 않습니다. 중요한 것은 차이점,> 및 <또는 공백을보고 싶지 않다는 것입니다.

grep -FvF 큰 파일이 아닌 작은 파일에 대한 트릭을 수행했습니다.

첫 번째 파일에는 5 백만 개 이상의 줄이 있고 두 번째 파일에는 1300 개가 있습니다.

results.csv는 ~ 4,998,700 줄이됩니다.

나는 또한 grep -F -x -v -f 작동하지 않는 것을 시도했다 .



1
@Tim 나는 당신의 링크를 보았고 나는 오래된 회원이므로 규칙을 알고 있지만 부주의했습니다. 죄송합니다 :) 편집 중이었고 게시물이 편집되었다는 팝업을 보았습니다. 고마워요
Lynob 2016 년

50,25,125,310두 파일에 공통입니다. 원하는 출력에서 ​​파일을 제거해야합니다.
heemayl

순서를 유지해야합니까?
kos

1
정보의 종류와 관련하여 diff, IMO는 패치를 만들기위한 것입니다. 어쨌든, 나는 지금 당신의 최고의 도구, diff, grep, awk 또는 perl을 확신합니다.
Panther

답변:


20

다음과 같은 직업처럼 들립니다 comm.

$ comm -3 <(sort test1.csv) <(sort test2.csv)
100,300,500,700
    100,4,2,1,7
    21,22,23,24,25
    50,25,700,5

에 설명 된대로 man comm:

   -1     suppress column 1 (lines unique to FILE1)

   -2     suppress column 2 (lines unique to FILE2)

   -3     suppress column 3 (lines that appear in both files)

따라서 -3파일 중 하나에 고유 한 행만 인쇄됩니다. 그러나 파일은 찾은 파일에 따라 들여 쓰기됩니다. 탭을 제거하려면 다음을 사용하십시오.

$ comm -3 <(sort test1.csv) <(sort test2.csv) | tr -d '\t'
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5

이 경우 실제로 파일을 정렬 할 필요가 없으며 위의 내용을 단순화하여 다음을 수행 할 수 있습니다.

comm -3 test1.csv test2.csv | tr -d '\t' > difference.csv

당신은 200,[...]선 허 후 공간에 속지 않았다 ? :)
kos

@ kos 아니오, 파일에서 후행 공백을 먼저 제거했습니다. OP의 파일에는 실제로 해당 파일이 없다고 가정했습니다.
terdon

6

프로세스 대체 grep와 함께 사용 bash:

$ cat <(grep -vFf test2.csv test1.csv) <(grep -vFf test1.csv test2.csv)
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5

출력을 results.csv다음 과 같이 저장하려면

cat <(grep -vFf test2.csv test1.csv) <(grep -vFf test1.csv test2.csv) >results.csv
  • <()는 IS bash프로세스 교체 패턴

  • grep -vFf test2.csv test1.csv 유일한 라인을 찾을 것입니다 test1.csv

  • grep -vFf test1.csv test2.csv 유일한 라인을 찾을 것입니다 test2.csv

  • 마지막으로 우리는 결과를 요약합니다. cat

또는 Oli가 제안한 것처럼 명령 그룹화를 사용할 수도 있습니다.

$ { grep -vFf test2.csv test1.csv; grep -vFf test1.csv test2.csv; }
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5

또는 둘 다 STDOUT에 쓰고 있으므로 궁극적으로 추가됩니다.

$ grep -vFf test2.csv test1.csv; grep -vFf test1.csv test2.csv
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5

1
cat두 개의 리디렉션 된 명령이 필요한 이유는 무엇 입니까? 왜 다른 하나를 달리지 않겠습니까? grep ... ; grep ...또는 { grep ... ; grep ... ; }집단 출력으로 무언가를 원한다면.
Oli

@Oli Thanks..thats은 훌륭한 idea..i는 .. 생각하지 않았다
heemayl

4

행의 순서는 관련이없는 경우, 사용 awk또는 perl:

awk '{seen[$0]++} END {for (i in seen) {if (seen[i] == 1) {print i}}}' 1.csv 2.csv

사용은 grep공통의 선을 얻고 그 출력을 필터링합니다 :

grep -hxvFf <(grep -Fxf 1.csv 2.csv) 1.csv 2.csv

내부 그렙은 공통 선을 얻은 다음 외부 그렙은 이러한 공통 선과 일치하지 않는 선을 찾습니다.


awk 명령은 다시 구현 sort | uniq -u되어 하나의 파일에 중복 줄이 있으면 잘못된 대답을 제공합니다. grep의 경우 "내부"/ "외부"가 아니라 "내부"/ "외부"라고 말합니다.
Peter Cordes 2016 년

@PeterCordes 네, 그렇습니다. 누가 이것이 잘못된 결과라고 말합니까?
muru

그 구석의 경우 질문이 정확히 요구 한 것이 아니라는 점에서 잘못되었습니다. 다른 사람이 원하는 것일 수도 있지만 awk인쇄 할 내용과 인쇄 할 내용 comm -3diff답변 의 차이점을 지적해야합니다 .
Peter Cordes

@PeterCordes 다시, 당신은 누구라고 말합니까? OP가 그것이 원하는 것이라고 말할 때까지 출력이의 출력과 다른지 상관하지 않습니다 comm -3. 이유는 어떤 이유가 표시되지 않습니다 내가 그것을 설명해야한다. 메모를 편집하려면 자유롭게 느끼십시오.
muru

OP는 차이를 원한다고 말했다. 항상 프로그램이 생산하는 것은 아닙니다. 하나의 테스트 케이스에 대해 동일한 출력을 생성하지만 모든 경우에 대해 작성된 설명을 만족시키지 않는 프로그램에는 헤드 업이 필요합니다. 나는 그것을 말하려고 여기 있으며, 내가 누구인지 또는 누구인지에 관계없이 사실입니다. 메모를 추가했습니다.
Peter Cordes 2016 년

4

--*-line-format=...옵션을 사용하십시오diff

diff필요한 것을 정확하게 말할 수 있습니다 -아래 설명 :

diff --old-line-format='%L' --new-line-format='%L' --unchanged-line-format='' f1.txt f2.txt

printf숫자 형식 과 유사하게 diff의 출력을 매우 자세한 방식으로 지정할 수 있습니다.

첫 번째 파일의 줄은 test1.csv"오래된"줄이며 두 번째 파일 의 줄 test2.csv은 "새"줄입니다. diff파일에서 변경된 내용을 볼 때 사용하는 것이 좋습니다.

필요한 옵션은 "오래된"라인, "새"라인 및 "변경되지 않은"라인의 형식을 설정하는 옵션입니다.
필요한 형식은 매우 간단합니다.
새로운 줄과 오래된 줄의 경우 줄의 텍스트 만 출력하려고합니다. %L행 텍스트의 형식 기호입니다.
변경되지 않은 행에 대해서는 아무 것도 표시하지 않습니다.

--old-line-format='%L'이를 통해 예제 데이터를 사용하여와 같은 옵션을 작성 하고 모두 모을 수 있습니다.

$ diff --old-line-format='%L' --new-line-format='%L' --unchanged-line-format='' test1.csv test2.csv
100,4,2,1,7
100,300,500,700
21,22,23,24,25
50,25,700,5


성능에 대한 참고 사항

파일 크기가 다르므로 입력 파일이 중요하지 않은 경우 입력 파일을 교환하십시오. 내부 작업 diff이 다른 방법보다 더 잘 처리 할 수 ​​있습니다. 메모리가 적거나 계산량이 적을수록 좋습니다.

diff큰 파일과 함께 사용하기위한 최적화 옵션이 있습니다 --speed-large-files. 파일 구조에 대한 가정을 사용하므로 귀하의 경우에 도움이되는지 확실하지 않지만 시도해 볼 가치가 있습니다.

형식 옵션은 man diff아래에 설명되어 있습니다 --LTYPE-line-format=LFMT.


3

순서를 유지할 필요가 없으므로 간단히 다음을 수행하십시오.

sort test1.csv test2.csv | uniq -u
  • sort test1.csv test2.csv: 병합 및 종류 test1.csvtest2.csv
  • uniq -u: 중복이없는 행만 인쇄합니다

한 파일에 한 줄이 두 번 포함되어 있으면 다른 파일에는 나타나지 않습니다. 두 경우 모두 diff결과 가 될 것 입니다.
Volker Siegel
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.