파일의 특정 열에 대해 diff를 사용할 수 있습니까?
파일 1
Something 123 item1
Something 456 item2
Something 768 item3
Something 353 item4
파일 2
Another 123 stuff1
Another 193 stuff2
Another 783 stuff3
Another 353 stuff4
출력 (예상)
Something 456 item2
Something 768 item3
Another 193 stuff2
Another 783 stuff3
각 파일의 두 번째 열을 원하면 diff
결과에 차이 열이 포함되지만 전체 행이 포함됩니다.
답변1
awk
파일 열을 비교하는 데 더 나은 도구입니다. 예를 들어 다음 질문에 대한 답변을 참조하세요.서로 다른 파일의 두 열을 비교하고 일치하면 인쇄합니다.-- 열과 일치하는 행을 인쇄하는 데에도 비슷한 답변이 있습니다.
라인을 인쇄하고 싶기 때문에아니요awk
일치하면 file2의 열 2에 포함된 줄을 인쇄하는 명령을 만들 수 있습니다 .아니요file1을 참조하세요.
$ awk 'NR==FNR{c[$2]++;next};c[$2] == 0' file1 file2
Another 193 stuff2
Another 783 stuff3
terdon에서도 비슷하게 설명했듯이위의 질문,
NR==FNR
: NR은 현재 입력 라인 번호이고, FNR은 현재 파일의 라인 번호입니다. 두 파일은 첫 번째 파일을 읽는 경우에만 동일합니다.c[$2]++; next
: 첫 번째 파일인 경우 두 번째 필드를c
배열로 저장합니다. 그런 다음 첫 번째 파일에만 적용되도록 다음 줄로 이동합니다.c[$2] == 0
: else 블록은 이것이 두 번째 파일인 경우에만 실행되므로 해당 파일의 필드 2가 이미 표시되었는지 확인하고(c[$2]==0
), 그렇다면 해당 행을 인쇄합니다. 에서awk
기본 작업은 줄을 인쇄하는 것이므로c[$2]==0
true인 경우 줄이 인쇄됩니다.
그러나 열 2가 file2의 행과 일치하지 않는 file1의 행도 원합니다. 동일한 명령에서 위치를 간단히 바꾸면 이를 얻을 수 있습니다.
$ awk 'NR==FNR{c[$2]++;next};c[$2] == 0' file2 file1
Something 456 item2
Something 768 item3
이제 이를 두 번 사용하여 원하는 출력을 생성할 수 있습니다 awk
. 아마도 더 많은 전문 지식을 가진 사람 awk
이 한 번에 할 수 있을 것입니다.
질문에 태그를 달았 /ksh
으므로 korn 쉘을 사용하고 있다고 가정합니다. ksh
예를 들어 diff에 대한 함수를 정의하여 작업을 더 쉽게 만들 수 있습니다 diffcol2
.
diffcol2()
{
awk 'NR==FNR{c[$2]++;next};c[$2] == 0' $2 $1
awk 'NR==FNR{c[$2]++;next};c[$2] == 0' $1 $2
}
이것은 원하는 동작을 갖습니다:
$ diffcol2 file1 file2
Something 456 item2
Something 768 item3
Another 193 stuff2
Another 783 stuff3
답변2
나는 diff가 (cut과 결합하더라도) 이것을 처리할 만큼 충분히 유연하지 않다고 생각합니다. 실제로 원하는 것은 file2에 없는 file1의 키이고 그 반대의 경우도 마찬가지입니다. 엄밀히 말하면 한 줄씩 차이가 있는 것은 아닙니다. 입력 파일이 크면 Perl을 사용하지만 작은 파일의 경우 이 awk 스크립트는 제공된 입력으로 작동합니다.
%cat a.awk
BEGIN {
while (getline < "file1") {
line=$0;
split(line,f," ");
key=f[2];
f1[key]=line
}
while (getline < "file2") {
line=$0;
split(line,f," ");
key=f[2];
f2[key]=line
}
}
END {
for (c in f1) {
if (c in f2 == 0) print f1[c]
}
for (c in f2) {
if (c in f1 == 0) print f2[c]
}
}
실행 방법은 다음과 같습니다(awk에는 입력 파일이 인수로 필요하므로 /dev/null 트릭에 유의하세요.
%awk -f a.awk /dev/null
Something 456 item2
Something 768 item3
Another 193 stuff2
Another 783 stuff3
답변3
다음과 같은 방법으로 한 번에 작업을 수행할 수 있습니다.
$ awk '{t[$2]=t[$2]$0"\n";NR==FNR?a[$2]=1:b[$2]=1}END{for(i in t)if(a[i]!=b[i])printf"%s",t[i]}' file1 file2
Another 193 stuff2
Something 456 item2
Something 768 item3
Another 783 stuff3
설명하다:
- 각 행에 대해 다음을 수행합니다.
{t[$2]=t[$2]$0"\n";
t
해당 키로 인덱싱된 테이블에서 동일한 키를 가진 모든 행을 조인합니다.NR==FNR?a[$2]=1:b[$2]=1}
키가 첫 번째 파일에 있으면a
테이블에 넣고, 그렇지 않으면b
;
END
마지막에:{for(i in t)
표의 각 키에 대해 다음을 수행합니다t
.if(a[i]!=b[i])
키가 하나의 파일에만 존재하는 경우:printf"%s",t[i]}
모든 행을 인쇄하려면 이 키를 사용하십시오.
이는 키가 중복된 경우(키 없이 다른 파일의 모든 줄을 인쇄하는 경우)에도 작동하지만 줄의 순서는 유지되지 않습니다(줄은 키별로 사전순으로 인쇄됩니다).