Bash: criando listas de palavras

0

Estou tentando produzir todas as combinações possíveis entre {a..z} e {0..9}; esta saída sem usar ferramentas como crunch :

$ head wordlist.txt

a
b
c
1
2
3
aa
ab
ac
a1

$ tail wordlist.txt

333332c
3333321
3333322
3333323
333333a
333333b
333333c
3333331
3333332
3333333

Podemos fazer com regex? Eu tentei combinações de coisas como:

for i in $(<magic here>); do
  echo "$i"
done

Mas isso não me levou a lugar nenhum ...

    
por user809474 03.11.2017 / 04:32

2 respostas

1

O problema é que isso se torna muito rápido: todas as permutações de 6 caracteres ao longo de 36 (minúsculas + dígitos): 36 ** 6 = 2176782336, que são 2176 milhões. Multiplique pelo tamanho (6) e você precisa de 12 Gigabytes. Então você não pode realmente gerar toda a lista. Se você não pode usar "geradores" como em Python (que geram valores de loop conforme necessário), é necessário fazer algo como:

for t1 in $chars; do 
    for t2 in $chars; do 
        for t3 in $chars; do 
            for t4 in $chars; do 
                for t5 in $chars; do
                    echo $t1$t2$t3$t4$t5
                done
            done
        done
    done
done

Se você precisar de strings mais curtas:

#! /bin/bash

chars=('' a b c)

for t1 in "${chars[@]}"; do 
    for t2 in "${chars[@]}"; do 
        for t3 in "${chars[@]}"; do
            echo $t1$t2$t3
        done
    done
done

De acordo com o meu monitor de sistema, o código não aumenta significativamente a memória usada pelo processo bash (em torno de 2MB, enquanto produz 29.5MB de saída de acordo com pv -b ). Para comparação, este código equivalente (com listas ligeiramente mais curtas):

for t in {a..t}{a..t}{a..t}{a..t}{a..t} ; do 
    echo $t
done

Leva 600MB de RAM para rodar.

Escolha sabiamente:)

    
por 03.11.2017 / 13:56
0

Dependendo de quão preciso você precisa, e da sobrecarga tolerável, você pode conseguir algo como

echo {\ ,{A..Z},{a..z},{0..9}}{\ ,{A..Z},{a..z},{0..9}}{\ ,{A..Z},{a..z},{0..9}}

Onde você repetiria o bit {\, {A..Z}, {a..z}, {0..9}} para cada conjunto, ou seja, se você quiser cada palavra para ter no máximo 10 caracteres, você repetiria 10 vezes.

Existe uma deficiência no código (porque ele não reconhece "nenhum caractere" no início, usei "" como um espaço reservado. Isso criará duplicatas - ou seja, "99" e "99". Você pode se livrar deles, empurrando-o através de um filtro uniq (e talvez usando tr também), mas dependendo da sua aplicação e do tamanho da saída final, você pode ter dificuldades com o tempo que levará para criar o arquivo final. lista.

Para criar uma lista que produzirá todas as permutações sem duplicatas, mas em uma ordem diferente da entrada original, você poderá usar

for each in {\ ,{A..Z},{a..z},{0..9}}{\ ,{A..Z},{a..z},{0..9}}{\ ,{A..Z},{a..z},{0..9}} ; do  echo $each; done | tr -d " " | sort -u
    
por 03.11.2017 / 08:19