AWK를 사용하여 두 개의 텍스트 파일 병합

AWK를 사용하여 두 개의 텍스트 파일 병합

저는 awk에 대한 경험이 많지 않아서 한 가지 문제를 극복하기 위해 애쓰고 있습니다. file1.txt와 file2.txt라는 두 개의 파일이 있습니다. 파일1.txt:

20 101 1 2 3 4
20 102 5 6 7 8
20 108 3 3 3 3

파일2.txt:

20 100 99 99 99 99
20 101 11 22 33 44
20 103 55 66 77 88

각 파일의 처음 두 열 뒤에는 항상 4개의 값이 있습니다.

내가 하려는 것은 이 파일들을 하나로 병합하는 것입니다. 저는 첫 번째와 두 번째 열로 그것들을 연결하고 있습니다.

결과 파일에는 10개의 열이 있어야 합니다. 처음 두 개는 핵심 항목이고, 다음 4개 열은 첫 번째 파일의 값이고, 마지막 4개는 두 번째 파일의 값입니다.

결과 파일에서 두 번째 파일과 일치하지 않는 첫 번째 파일의 모든 레코드(또는 그 반대)에는 누락된 값을 나타내는 추가 0이 포함됩니다.

모든 것은 공백 문자로 구분됩니다.

결과는 다음과 같아야 합니다.

20 100 0 0 0 0 99 99 99 99
20 101 1 2 3 4 11 22 33 44
20 102 5 6 7 8 0 0 0 0
20 103 0 0 0 0 55 66 77 88
20 108 3 3 3 3 0 0 0 0

이것은 웹을 검색하는 동안 찾은 awk 스크립트를 수정한 것입니다.

BEGIN {                                                                                                                
   OFS=" "
}                                      
{                               
   i=$1 OFS $2 #Making key out of first and second field of the first file                    
}
   NR==FNR {                             
   A[i]=$0  #Saving records from first file to an array using first two columns as index                           
   next
}
#Next part assumes that I'm reading file2.txt                                         
i in A {                                
   printf "%s",A[i]  #Here, I have a match with first file, and I want to print the joined record I saved from file1.txt                                                                                               
   print $3,$4,$5,$6 #In order to print a joined record, after printing record from first file, I'm printing columns from the second file                                                                                           
   delete A[i]                           
   next
}

{ #Here I print records from file2.txt that don't have a match with file1.txt, and put zeroes to fill missing values
   print 0,0,0,0,$3,$4,$5,$6
}
END { #In the END block I'm printing everything from file1.txt that doesn't have a match and print zeroes aftewards to fill missing values
   for (i in A) {  printf "%s",A[i]; print 0,0,0,0  }                           
}

결과는 두 번째 열을 기준으로 정렬되며 모든 누락된 값은 0으로 채워집니다. 그러나 현재 얻고 있는 결과는 다음과 같습니다.

20 100 0 0 0 0 99 99 99 99
11 22 33 443 4
20 103 0 0 0 0 55 66 77 88
20 108 3 3 3 3 0 0 0 0
0 0 0 0 6 7 8

파일이 정렬되지 않았다는 사실에도 불구하고(항상 sort -k 2를 사용할 수 있음) 일부 줄은 내가 의도한 대로 인쇄되지 않으며 일반적으로 A의 요소를 인쇄할 수 없는 이유를 설명할 수 없습니다. 정렬. 일시적으로 ORS를 변경하거나(출력이 전혀 없음) printf 대신 print를 사용하는 등(결과도 이상해 보입니다) 다양한 시도를 했습니다.

경험 부족으로 인해 몇 가지 추가 질문이 제기됩니다.

이 작업을 완료하기 위해 awk를 사용하는 것이 합리적입니까? 나는 사용해 보았습니다.가입하다, 그러나 끝에 개행 문자가 있는 열을 인쇄할 수 없었기 때문에 결국 중단되었습니다. 어쩌면 Python 스크립트가 더 유용할까요?

병합을 위해 매우 큰 파일을 사용할 것이라는 점을 고려하면 메모리 측면에서 배열을 사용하는 것이 합리적입니까?

미리 감사드립니다!

답변1

awk '!second { file1vals[$1 FS $2]=$0 }
      second { print (($1 FS $2 in file1vals)?file1vals[$1 FS $2]: $1 FS $2 FS "0 0 0 0") FS $3, $4, $5, $6;
               delete file1vals[$1 FS $2]
             }
END{ for(x in file1vals) print file1vals[x], "0 0 0 0" }' file1 second=1 file2

첫 번째 항목을 로드하기에 충분한 메모리가 있는 한 작동합니다.파일1기억 속으로.

첫 번째 블록에서는 !second {...}첫 번째 파일일 때만 실행되고 우리는파일1배열의 키로 첫 번째 & 두 번째 열 쌍의 관련 배열에 넣습니다 .

두 번째 파일인 경우에만 실행되는 두 번째 블록에서는 second {...}두 파일의 키가 일치하는 결합된 행을 인쇄합니다. 그렇지 않으면 키와 0을 인쇄한 다음 나머지 열을 인쇄합니다.파일2; 그런 다음 delete file1vals[$1 FS $2]두 파일에 키가 있던 배열에서 키도 삭제합니다 .

END의 마지막 블록에서는 다음과 관련된 나머지 일치하지 않는 키를 인쇄합니다.파일1.

관련 정보