Todas as combinações possíveis de caracteres e números

10

Por isso, quero gerar todas as combinações possíveis de caracteres e números minúsculos e maiúsculos que podem formar uma cadeia de 5 caracteres.

Possibilidades: a..z, A..Z e 0..9.

Existe alguma maneira elegante de fazer isso em tudo?

    
por ardevd 18.05.2015 / 14:20

6 respostas

10

Aqui está uma solução bash que leva o tamanho desejado como parâmetro (você faria permute 5 no seu caso):

#!/bin/bash
charset=({a..z} {A..Z} {0..9})
permute(){
  (($1 == 0)) && { echo "$2"; return; }
  for char in "${charset[@]}"
  do
    permute "$((${1} - 1 ))" "$2$char"
  done
}
permute "$1"

É dolorosamente lento, no entanto. Ouso eu recomendo C? link

#include <stdio.h>

//global variables and magic numbers are the basis of good programming
const char* charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
char buffer[50];

void permute(int level) {
  const char* charset_ptr = charset;
  if(level == -1){
    puts(buffer);
  }else {
   while(buffer[level]=*charset_ptr++) {
    permute(level - 1);
   }
  }
}

int main(int argc, char **argv)
{

  int length;
  sscanf(argv[1], "%d", &length); 

  //Must provide length (integer < sizeof(buffer)==50) as first arg;
  //It will crash and burn otherwise  

  buffer[length]='
make CFLAGS=-O3 permute && time ./permute 5 >/dev/null #about 20s on my PC
'; permute(length - 1); return 0; }

Execute:

#!/bin/bash
charset=({a..z} {A..Z} {0..9})
permute(){
  (($1 == 0)) && { echo "$2"; return; }
  for char in "${charset[@]}"
  do
    permute "$((${1} - 1 ))" "$2$char"
  done
}
permute "$1"

As linguagens de alto nível são contra o uso de força bruta (que é basicamente o que você está fazendo).

    
por 18.05.2015 / 15:30
6

Em bash , você pode tentar:

printf "%s\n" {{a..z},{A..Z},{0..9}}{{a..z},{A..Z},{0..9}}{{a..z},{A..Z},{0..9}}{{a..z},{A..Z},{0..9}}{{a..z},{A..Z},{0..9}}

mas isso levaria uma eternidade e consumiria toda a sua memória. Melhor seria usar outra ferramenta como perl :

perl -le '@c = ("A".."Z","a".."z",0..9);
          for $a (@c){for $b(@c){for $c(@c){for $d(@c){for $e(@c){
            print "$a$b$c$d$e"}}}}}'

Cuidado com 6 x 62 5 bytes, portanto, 5.496.796.992.

Você pode fazer o mesmo loop em bash , mas bash é o shell mais lento no oeste, o que levará horas:

export LC_ALL=C # seems to improve performance by about 10%
shopt -s xpg_echo # 2% gain (against my expectations)
set {a..z} {A..Z} {0..9}
for a do for b do for c do for d do for e do
  echo "$a$b$c$d$e"
done; done; done; done; done

(no meu sistema, isso gera 700 kiB / s em vez de 20MiB / s com o equivalente perl ).

    
por 18.05.2015 / 14:31
4

Aqui está uma maneira de fazer isso puramente no bash sem ter que morder 5 GB de memória:

for c1 in {A..Z} {a..z} {0..9}
do
    for c2 in {A..Z} {a..z} {0..9}
    do
        for c3 in {A..Z} {a..z} {0..9}
        do
            for c4 in {A..Z} {a..z} {0..9}
            do
                for c5 in {A..Z} {a..z} {0..9}
                do
                    printf "%s\n" "$c1$c2$c3$c4$c5"
                done
            done
        done
    done
done
    
por 18.05.2015 / 14:55
2

Esta versão bash ainda não é tão rápida quanto Perl, mas é cerca de quatro vezes mais rápida que cinco loops aninhados:

printf -vtwo "%s " {{a..z},{A..Z},{0..9}}{{a..z},{A..Z},{0..9}}
for three in {{a..z},{A..Z},{0..9}}{{a..z},{A..Z},{0..9}}{{a..z},{A..Z},{0..9}}; do
    printf "$three%s\n" $two;
done
    
por 20.05.2015 / 03:38
0

Você pode usar crunch (que está disponível pelo menos nas distribuições de Kali).

crunch 5 5 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890
    
por 07.06.2018 / 16:39
0

Bem, elegante, sim (ATENÇÃO: pode bloquear o seu computador ;-)):

eval echo $(printf "%s" '{{a..b},{A..B},{0..1}}'{,,,,,})
    
por 09.06.2018 / 08:34

Tags