Gerador de combinação com gerenciamento de memória e recursos

2

Eu tenho este script bash, que está gerando cada combinação de matrizes em 5 dígitos:

#!/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

Isso produzirá:

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

No entanto, isso é apenas congelar meu computador. Existe alguma maneira de gravar os dados no arquivo cada vez mais? Além disso, é possível separar a saída para arquivos diferentes, por exemplo, a cada 65536 linhas? como output1.txt, output2.txt, output3.txt?

Obrigado pela sua ajuda!

    
por Lanti 18.11.2015 / 09:54

5 respostas

3

Eu encontrei uma boa ferramenta chamada crunch , que está escrita em C. Você também tem opções para separar os arquivos de saída por tamanho de arquivo ou linhas!

Instale: $ sudo apt-get install crunch

#!/usr/bin/env bash

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

Esse comando na pasta de saída gera aaaaa-awrdd.txt, awrde-bi8gh.txt, bi8gi-b5pjl.txt, etc. arquivos exatamente com 1.048.576 linhas, que é o limite de linha do Excel 2007+. É também uma solução super rápida. geração de 60.000.000 + combinações em 58 arquivos tomados apenas 10s! Perfeito!

    
por 18.11.2015 / 12:09
6

É difícil gerar essa grande permutação sem manter uma memória enorme no shell.

Você pode tentar outro idioma, como o 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
    
por 18.11.2015 / 10:53
5

Você pode usar loops aninhados, embora seja lento:

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
    
por 18.11.2015 / 11:17
2

Para permutações, eu uso o seguinte script perl para gerar permutações:

#!/usr/bin/perl
use strict;
use Algorithm::Permute;

my $q=shift or die("usage permgen n word-set\n");

my $p = new Algorithm::Permute([@ARGV],$q);
while (my @res = $p->next) { 
  print @res,"\n"; }

Isso pode ser usado para fazer permutações de conjuntos muito diferentes. Exemplo de dados unicode:

permgen 2  ⚀ ⚁ ⚂ ⚃ ⚄ ⚅ | shuf -n 2
⚅⚄
⚅⚁

Para gerar seu exemplo (ENORME), precisamos escrever: permgen 5 {a..z} {0..9}

Na minha máquina antiga, são necessários 2s para gerar 1_000_000 permutações

time permgen 5 {a..z} {1..9}| head -1000000| wc

    
por 18.11.2015 / 12:00
2

bash sempre alocará todos os elementos na RAM antes de iterar sobre eles com o loop for . Você está efetivamente pedindo a bash para alocar muita RAM de uma só vez e seu computador simplesmente não tem muito, por isso ele trava / congela.

As combinações em si não exigem muito (minhas computações no fundo do envelope dão cerca de 500MB), mas suponho que bash tenha uma sobrecarga enorme ao lidar com matrizes.

Eu me pergunto quanta memória livre você realmente tem.

    
por 18.11.2015 / 17:37

Tags