次の形式のデータを含む非常に大きなファイル(〜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
ます。paste
file2
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の相対速度に応じて、paste
awkなどのより柔軟な方法で複数のファイルを処理できるツールを使用しない方が速いかもしれません。これは、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
必要に応じて開きます。失敗した場合(ファイルの終わりに達したため)、ファイルを閉じて再起動してください。