GNU diff
출력 에서 이전 / 새 / 변경되지 않은 행의 형식을 제어하여이를 달성 할 수 있습니다 .
diff --new-line-format="" --unchanged-line-format="" file1 file2
이 작업을 수행하려면 입력 파일 을 정렬해야합니다 . bash
(및 zsh
)을 사용하면 프로세스 대체를 사용하여 적절하게 정렬 할 수 있습니다 <( )
.
diff --new-line-format="" --unchanged-line-format="" <(sort file1) <(sort file2)
위의 새 줄 과 변경되지 않은 줄은 표시 되지 않으므로 변경된 줄만 출력됩니다 (예 : 제거 된 줄). 당신은 또한 몇 가지 사용할 수 있습니다 diff
같은 다른 솔루션이 제공하지 않는 옵션 -i
의 경우, 또는 다양한 공백 옵션 (무시 -E
, -b
, -v
덜 엄격한 매칭 등).
설명
옵션은 --new-line-format
, --old-line-format
그리고 --unchanged-line-format
당신이 방법은 제어 할 수 diff
비슷한 차이, 포맷 printf
형식 지정자를. 이 옵션은 각각 새 (추가), 이전 (제거) 및 변경되지 않은 행 을 형식화합니다 . 1을 비워 ""로 설정하면 해당 종류의 행이 출력되지 않습니다.
통합 diff 형식에 익숙한 경우 다음을 사용하여 부분적으로 다시 만들 수 있습니다.
diff --old-line-format="-%L" --unchanged-line-format=" %L" \
--new-line-format="+%L" file1 file2
%L
지정 문제의 선이며, 우리는 "+" "각 접두사 -처럼,"또는 "" diff -u
(그것은 단지 출력 차이, 그것이 부족합니다 ---
+++
및 @@
각 그룹화 변화의 상단 선). 당신은 또한 같은 다른 유용한 일을하려면이 옵션을 사용할 수있는 번호를 각 라인 에 %dn
.
이 diff
방법은 (다른 제안 comm
과 함께 및 join
) 정렬 된 입력 으로 예상 출력 만 생성 하지만 <(sort ...)
정렬 하는 데 사용할 수 있습니다 . 여기에 간단 awk
(nawk) 스크립트 (스크립트에 의해 영감은 연결된에 Konsolebox의 대답) 임의의 입력 파일을 정렬 받아들이, 그리고 그들이 FILE1에서 발생하는 순서에 누락 된 라인을 출력합니다.
# output lines in file1 that are not in file2
BEGIN { FS="" } # preserve whitespace
(NR==FNR) { ll1[FNR]=$0; nl1=FNR; } # file1, index by lineno
(NR!=FNR) { ss2[$0]++; } # file2, index by string
END {
for (ll=1; ll<=nl1; ll++) if (!(ll1[ll] in ss2)) print ll1[ll]
}
이것은 file1의 전체 내용을 한 줄씩 색인 배열 ll1[]
로 저장하고 file2의 전체 내용을 한 줄씩 색인 연관 배열로 저장 ss2[]
합니다. 두 파일을 모두 읽은 후 반복 ll1
하여 in
연산자를 사용하여 file1의 행이 file2에 있는지 판별하십시오. ( diff
중복이 있으면 메소드 와 다른 출력을 갖습니다 .)
파일이 충분히 커서 파일을 모두 저장하는 데 메모리 문제가 발생하는 경우 file1 만 저장하고 file2를 읽는 동안 일치 항목을 삭제하여 CPU를 메모리로 교환 할 수 있습니다.
BEGIN { FS="" }
(NR==FNR) { # file1, index by lineno and string
ll1[FNR]=$0; ss1[$0]=FNR; nl1=FNR;
}
(NR!=FNR) { # file2
if ($0 in ss1) { delete ll1[ss1[$0]]; delete ss1[$0]; }
}
END {
for (ll=1; ll<=nl1; ll++) if (ll in ll1) print ll1[ll]
}
두 어레이의 상기 저장 FILE1의 전체 내용을, 행 번호에 의해 인덱싱 하나 ll1[]
, 광고 내용에 의해 인덱싱 하나 ss1[]
. 그런 다음 file2를 읽으면 일치하는 각 줄이 ll1[]
및 에서 삭제됩니다 ss1[]
. 마지막에는 원래 순서를 유지하면서 file1의 나머지 행이 출력됩니다.
이 경우 언급 한 문제로 GNU를 사용하여 나누고 정복 할 수 있습니다 split
(필터링은 GNU 확장입니다).
split -l 20000 --filter='gawk -f linesnotin.awk - file2' < file1
의 사용 및 배치 참고 -
의미 stdin
상의 gawk
명령 줄을. 이것은 split
호출 당 20000 라인 청크 단위로 file1에서 제공 됩니다.
비 GNU 시스템에 대한 사용자의 경우, 거의 확실하게 존재는 GNU로 coreutils이의 일환으로 OSX에 포함, 당신이 얻을 수있는 패키지 애플의 Xcode GNU를 제공하는 도구 diff
, awk
하지만 단지 POSIX / BSD split
가 아닌 GNU 버전.
awk 'NR==FNR{a[$0];next}!($0 in a)' file2 file1 > out.txt