各行を他のファイルの行と費用効果的に関連付ける

各行を他のファイルの行と費用効果的に関連付ける

次の形式のデータを含む非常に大きなファイル(〜10 Gbデータ)があります。

'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

これは2回反転する必要がありますfile1。 CPUとI / Oの相対速度に応じて、pasteawkなどのより柔軟な方法で複数のファイルを処理できるツールを使用しない方が速いかもしれません。これは、2つのファイルのうちの1つをメモリに完全にロードする必要がないawkソリューションです(file2ファイルが小さい場合、ディスクキャッシュはそれを処理します)。

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

説明:getline s <file2行の次の行を読み、file2必要に応じて開きます。失敗した場合(ファイルの終わりに達したため)、ファイルを閉じて再起動してください。

関連情報