각 라인을 다른 파일의 라인과 비용 효과적으로 연결

각 라인을 다른 파일의 라인과 비용 효과적으로 연결

다음 형식의 데이터가 포함된 매우 큰 파일(~10Gb 데이터)이 있습니다.

'1','1'    
'2','2'    
'3','3'    
'4','4'    
'5','5'    
'6','6'    
'7','7'    
'8','8'    
'9','9'    
'10','10'

다른 파일의 형식(크기 300Kb)은 -

1,2    
1,3    
1,4    
1,5    
1,6    
1,7    
1,8    
1,9    
1,10    
2,1    
2,3    
2,4   
2,5    
2,6    
2,7    
2,8    
2,9

원하는 출력 -

'1','1','1,2',    
'2','2','1,3',    
'3','3','1,4',    
'4','4','1,5',    
'5','5','1,6',    
'6','6','1,7',    
'7','7','1,8',    
'8','8','1,9',    
'9','9','1,10',    
'10','10','2,1',

입력 파일에 천만 개가 넘는 레코드가 포함되어 있기 때문입니다. 따라서 루프를 통해 이 작업을 수행하는 것은 매우 비용이 많이 드는 작업입니다.

답변1

다음을 수행하십시오 -

awk 'FNR==NR{a[i++]=$0; max=i; next} 
{if ((NR % max) == 0) {i=max-1} else {i=(NR%max) - 1}; 
printf "%s,%s\n",$0,a[i]}' smaller_file larger_file

하지만 이보다 더 빠른 방법을 아시는 분 계시면 추천해주세요

답변2

더 작은 파일의 내용을 반복하려는 것 같습니다.

그리고awk

awk 'NR == FNR{a[++i]=$0; next}; 
 {print $0, a[FNR % i? FNR % i: i]}' smaller_file larger_file

그리고python

from itertools import cycle, izip
with open('larger_file') as f1, open('smaller_file') as f2:
    z = izip(f1, cycle(f2))
    for l, m in z:
           print l.rstrip('\n'), m.rstrip('\n')

답변3

paste -d",''," ./file1 - ./file2 - - </dev/null >out

...출력에 기록된 예제 데이터를 제공합니다.

'1','1','1,2',
'2','2','1,3',
'3','3','1,4',
'4','4','1,5',
'5','5','1,6',
'6','6','1,7',
'7','7','1,8',
'8','8','1,9',
'9','9','1,10',
'10','10','2,1',
,'2,3',
,'2,4',
,'2,5',
,'2,6',
,'2,7',
,'2,8',
,'2,9',
,'',

출력을 중지하는 기준이 무엇인지 정확하게 말하기는 다소 어렵지만 예제 출력과 동일한 출력을 작성합니다.

{   paste -d",''," ./file1 - ./file2 - - |
    sed -ne's/,/&/4p;t' -eq
}   </dev/null

'1','1','1,2',
'2','2','1,3',
'3','3','1,4',
'4','4','1,5',
'5','5','1,6',
'6','6','1,7',
'7','7','1,8',
'8','8','1,9',
'9','9','1,10',
'10','10','2,1',

답변4

이미 많은 분들이 지적하셨듯이,반죽올바른 도구입니다.

paste -d ,\'\' file1 /dev/null file2 /dev/null

file2그보다 짧으면 끝에 일치하는 빈 줄이 가능한 한 많이 있는 것으로 나타 file1납니다 .pastefile2

file2반복해서 반복 하려면 행 수에 도달할 때까지 반복해서 반복하세요 file1.

while true; do cat file2; done | head -n "$(wc -l file1)" |
paste -d ,\'\' file1 /dev/null - /dev/null

이건 두 번 뒤집어야 합니다 file1. CPU와 I/O의 상대적 속도에 따라 pasteawk와 같이 보다 유연한 방식으로 여러 파일을 처리할 수 있는 도구를 사용하지 않는 것이 더 빠를 수도 있습니다. 이는 두 파일 중 하나를 메모리에 완전히 로드할 필요가 없는 awk 솔루션입니다( file2파일이 작은 경우 디스크 캐시가 이를 처리합니다).

awk -v file2=file2 '
    !getline s <file2 {close(file2); getline s <file2}
    {print $0 ",\047" s "\047"}' file1

설명: getline s <file2줄의 다음 줄을 읽고 file2필요한 경우 엽니다. 실패하면(파일 끝에 도달했기 때문에) 파일을 닫고 다시 시작하십시오.

관련 정보