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개의 값이 있습니다.

내가 하고 싶은 것은 이 파일들을 하나로 병합하는 것입니다. 나는 그것들을 열 1과 열 2로 결합할 것입니다.

생성된 파일에는 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]두 파일 모두에 키가 존재하는 배열에서 키를 제거합니다.

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

관련 정보