メモリとリソース管理機能を備えた組み合わせジェネレータ

メモリとリソース管理機能を備えた組み合わせジェネレータ

すべての組み合わせに対して5桁の配列を生成するbashスクリプトがあります。

#!/usr/bin/env bash

for combo in \
{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,0,1,2,3,4,5,6,7,8,9}\
{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,0,1,2,3,4,5,6,7,8,9}\
{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,0,1,2,3,4,5,6,7,8,9}\
{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,0,1,2,3,4,5,6,7,8,9}\
{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,0,1,2,3,4,5,6,7,8,9};
do echo $combo;
done > output.txt

すると、以下が出力されます。

$ ./script.sh
aaaaa
aaaab
aaaac
...

しかし、これは私のコンピュータを停止します。徐々にファイルにデータを書き込む方法はありますか?また、出力をそれぞれ65536行ずつ別のファイルに分割できますか?出力1.txt、出力2.txt、出力3.txtのように?

ご協力ありがとうございます!

答え1

シェルから膨大な量のメモリを消費することなく、このような大きな置換を生成することは困難です。

Pythonなどの他の言語を試すことができます。

$ python -c '
  import itertools, string
  l = [c for c in string.ascii_lowercase + string.digits]
  for p in itertools.product(l, l, l, l, l): print "".join(p)
' > file

答え2

遅いですが、入れ子になったループを使用できます。

for p in {a..z} {0..9}
do for q in {a..z} {0..9}
 do for r in {a..z} {0..9}
  do for s in {a..z} {0..9}
   do for t in {a..z} {0..9}
    do echo $p$q$r$s$t
    done
   done
  done
 done 
done | split -l 65536 --numeric-suffixes=1 --additional-suffix=.txt - output

答え3

crunchIt's writing in Cという素晴らしいツールを見つけました。ファイルサイズまたは行ごとに出力ファイルを分割することもできます。

取付ける:$ sudo apt-get install crunch

#!/usr/bin/env bash

crunch 5 5 abcdefghijklmnopqrstuvwxyz0123456789 -o output/START -c 1048576 # Excel line limit

出力フォルダでこのコマンドで生成されたファイルaaaaa-awrdd.txt, awrde-bi8gh.txt, bi8gi-b5pjl.txt, etc.には、1.048.576行の正確な行が含まれています。これはExcel 2007 +行の制限です。これも非常に高速なソリューションです。わずか10秒で58ファイルから60,000,000以上の組み合わせを作成してください。完璧!

答え4

bashRAMのすべての要素は、ループ反復を使用する前に常に割り当てられますfor。本質的には、bash一度に大量のメモリを割り当てる必要がありますが、コンピュータにはそれほど多くのメモリがないため、クラッシュ/ハングが発生します。

bash組み合わせ自体はそれほど多くは必要ありませんが(おおよそ計算してみると500MB程度)、配列を扱う際に膨大なオーバーヘッドが発生しそうです。

利用可能なメモリがどれくらいになるかを正確に知りたいです。

関連情報