Todas as combinações possíveis de caracteres e números
13
Então, eu quero gerar todas as combinações possíveis de caracteres e números em maiúsculas e minúsculas que podem formar uma sequência de 5 caracteres.
Possibilidades: a..z, A..Z e 0..9.
Existe alguma maneira elegante de fazer isso no bash?
Deseja limitar-se ao ASCII ou ao script latino? E os diacríticos como sotaques (é, â ...)?
Stéphane Chazelas
Obrigado pelo seguimento. Post original atualizado para esclarecimentos.
Ardevd 18/05/19
Realmente precisa estar no bash? Será que um idioma como Perl ou awk funciona?
terdon
1
Então, por que não chamar Perl ou Python do bash? Especialmente com perl, é muito fácil usá-lo como uma linha.
terdon
2
Você está tentando aprender ou apenas quer o resultado? No segundo caso, existem muitos programas que fazem o trabalho como john the ripper ( john) e similares, o que lhe dará muitas possibilidades.
YoMismo
Respostas:
13
Aqui está uma solução bash que leva o comprimento desejado como parâmetro (você faria permute 5no seu caso):
#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]='\0';
permute(length -1);return0;}
Executá-lo:
make CFLAGS=-O3 permute && time ./permute 5>/dev/null #about 20s on my PC
Os idiomas de alto nível são péssimos com força bruta (que é basicamente o que você está fazendo).
@ Stéphane Chazelas Muito obrigado por essa edição. Eu estava escrevendo sujo, ignorando as citações "apropriadas", pois não são necessárias neste caso, mas sou muito grato pelos atalhos!
PSKocik 18/05
Eu tentei sua bashsolução. É muito bom; Eu gosto muito. Funcionou bem por cerca de 24 horas antes de eu perceber que meu sistema estava completamente bloqueado. Tentei algo semelhante com o `python; com um resultado semelhante, embora tenha sido consideravelmente mais rápido.
Cuidado com 6 x 62 5 bytes, portanto, 5.496.796.992.
Você pode fazer o mesmo loop bash, mas, bashsendo o shell mais lento do oeste, isso 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 dofor b dofor c dofor d dofor e do
echo "$a$b$c$d$e"done;done;done;done;done
(no meu sistema, isso gera 700 kiB / s em oposição a 20MiB / s com o perlequivalente).
Eu também acho que isso adicionaria à resposta se você adicionasse uma maneira de produzi-la em um arquivo; talvez como está sendo gerado para que ele não destruir a sua RAM, ou depois está tudo em cache na RAM
Hellreaver
2
@Hellreaver, todos eles gravam em um arquivo (no stdout, qualquer arquivo que esteja aberto; se executado em um terminal, um arquivo de dispositivo como /dev/pts/something; e você pode alterar isso com o operador de redirecionamento de shell), não na memória, mas o primeiro cria toda a saída na memória antes de enviá-la (para o arquivo aberto no stdout).
Stéphane Chazelas
4
Aqui está uma maneira de fazê-lo puramente no bash sem ter que consumir 5 GB de memória:
perl
, é muito fácil usá-lo como uma linha.john
) e similares, o que lhe dará muitas possibilidades.Respostas:
Aqui está uma solução bash que leva o comprimento desejado como parâmetro (você faria
permute 5
no seu caso):É dolorosamente lento, no entanto. Ouso recomendar C? https://youtu.be/H4YRPdRXKFs?t=18s
Executá-lo:
Os idiomas de alto nível são péssimos com força bruta (que é basicamente o que você está fazendo).
fonte
bash
solução. É muito bom; Eu gosto muito. Funcionou bem por cerca de 24 horas antes de eu perceber que meu sistema estava completamente bloqueado. Tentei algo semelhante com o `python; com um resultado semelhante, embora tenha sido consideravelmente mais rápido.Em
bash
, você pode tentar:mas isso levaria uma eternidade e gastaria toda a sua memória. O melhor seria usar outra ferramenta como
perl
:Cuidado com 6 x 62 5 bytes, portanto, 5.496.796.992.
Você pode fazer o mesmo loop
bash
, mas,bash
sendo o shell mais lento do oeste, isso levará horas:(no meu sistema, isso gera 700 kiB / s em oposição a 20MiB / s com o
perl
equivalente).fonte
/dev/pts/something
; e você pode alterar isso com o operador de redirecionamento de shell), não na memória, mas o primeiro cria toda a saída na memória antes de enviá-la (para o arquivo aberto no stdout).Aqui está uma maneira de fazê-lo puramente no bash sem ter que consumir 5 GB de memória:
fonte
Essa versão do bash ainda não é tão rápida quanto o Perl, mas é cerca de quatro vezes mais rápida que cinco loops aninhados:
fonte
Você pode usar
crunch
(disponível pelo menos nas distribuições Kali).fonte
Bem ... elegante ?, sim (apenas uma amostra rápida):
Essa expressão completa provavelmente irá bloquear o seu computador:
Uma opção sem bloqueio é usar vários loops:
Chame assim:
Onde o primeiro argumento é o número de caracteres e o segundo é a lista (separada por espaço) dos caracteres usados.
Isso criará uma variável (
loop
) com o script a ser executado e o último avaliação executará esse script. Por exemplo para:O valor de
loop
será:fonte
O Gnu Parallel pode fazer combinações, consulte https://www.gnu.org/software/parallel/ Algo assim:
fonte