문자와 숫자의 가능한 모든 조합


13

그래서 5 자 문자열을 구성 할 수있는 소문자와 대문자 및 숫자의 가능한 모든 조합을 생성하고 싶습니다.

가능성 : a..z, A..Z 및 0..9.

bash 에서이 작업을 수행하는 우아한 방법이 있습니까?


1
ASCII 또는 라틴 스크립트로 자신을 제한 하시겠습니까? 악센트 (é, â ...)와 같은 분음 부호는 어떻습니까?
Stéphane Chazelas 12

후속 감사합니다. 설명을 위해 원본 게시물을 업데이트했습니다.
ardevd

실제로 배쉬에 있어야 합니까 ? Perl 또는 awk와 같은 언어가 사용합니까?
terdon

1
그렇다면 왜 bash에서 Perl 또는 Python을 호출하지 않습니까? 특히와 함께 perl, 하나의 라이너로 사용하기가 매우 쉽습니다.
terdon

2
배우려고하거나 결과를 원하십니까? 두 번째 경우에는 john the ripper ( john) 등과 같은 작업을 수행하는 많은 프로그램이 있으며 , 이는 많은 가능성을 제공합니다.
YoMismo

답변:


13

다음은 원하는 길이를 매개 변수로 사용하는 bash 솔루션입니다 ( permute 5귀하의 경우).

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

그래도 고통스럽게 느립니다. C를 추천합니까? https://youtu.be/H4YRPdRXKFs?t=18s

#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);
  return 0;
}

그것을 실행 :

make CFLAGS=-O3 permute && time ./permute 5 >/dev/null #about 20s on my PC

고급 언어는 무차별 강제 (기본적으로 수행중인 작업)에 영향을줍니다.


@ Stéphane Chazelas 편집 해 주셔서 감사합니다. 이 경우에는 필요하지 않으므로 "적절한"따옴표를 무시하고 더럽게 쓰고 있었지만 바로 가기에 대해 매우 감사합니다!
PSkocik

나는 당신의 bash해결책을 시도했습니다 . 아주 좋다; 나는 그것을 많이 좋아. 시스템이 완전히 잠겨 있음을 알기 전에 약 24 시간 동안 제대로 작동했습니다. `python과 비슷한 것을 시도했습니다. 상당히 빨랐지만 비슷한 결과를 얻었습니다.
음성

8

에서가 bash, 당신은 시도 할 수 있습니다 :

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}}

그러나 그것은 영원히 걸리고 모든 기억을 소모합니다. 다음과 같은 다른 도구를 사용하는 것이 가장 좋습니다 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"}}}}}'

6 x 62 5 바이트이므로 5,496,796,992입니다.

같은 루프를 수행 할 수 bash있지만 bash서쪽에서 가장 느린 쉘이므로 몇 시간이 걸릴 것입니다.

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

(내 시스템에서는 20MiB / s와 반대로 700kiB / s로 출력 perl합니다).


또한 파일에 출력하는 방법을 추가하면 답변에 추가 될 것이라고 생각합니다. 어쩌면 그것이 생성되어 RAM을 파괴하지 않거나 RAM에 캐시 된 후에
Hellreaver

2
@Hellreaver, 모두 메모리에 저장되지 않고 파일에 저장합니다 (열려있는 모든 파일을 stdout에; 터미널에서 실행하는 경우 /dev/pts/something; 출력하기 전에 메모리의 전체 출력 (stdout에서 열린 파일로).
Stéphane Chazelas

4

다음은 5GB의 메모리를 소모하지 않고 bash에서 순수하게 수행하는 방법입니다.

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

2

이 bash 버전은 여전히 ​​Perl보다 빠르지는 않지만 5 개의 중첩 루프보다 약 4 배 빠릅니다.

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

1

사용할 수 있습니다 crunch(최소한 Kali 배포판에서 사용 가능).

crunch 5 5 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890

1

글쎄 ... 우아한?, 예 (빠른 샘플) :

eval echo $(printf "%s" '{{a..z},{A..Z},{0..9}}'{,,} )

이 완전한 표현은 대부분 컴퓨터를 차단합니다.

eval echo $(printf "%s" '{{a..z},{A..Z},{0..9}}'{,,,,} )

비 차단 옵션 중 하나는 여러 루프를 사용하는 것입니다.

nl=$'\n'; tab=$'\t'
n=${1:-3}
eval set -- "$2"

eval "varnames=($(echo {a..z}))"

for i in "${varnames[@]:0:$n}"; do
    header+='for '"$i"' do '
    middle+='$'"$i"
    traile+="done; "
done

loop="${header}${nl}    printf %s \"$middle\";${nl}$traile"
#echo "$loop"
eval "$loop"

다음과 같이 호출하십시오.

./script 3 '{a..z} {A..Z} {0..9}'

여기서 첫 번째 인수는 문자 수이고 두 번째 인수는 사용 된 문자 목록 (공백으로 구분)입니다.

그러면 loop실행할 스크립트로 변수 ( )가 작성되고 마지막 평가자는 해당 스크립트를 실행합니다. 예를 들면 다음과 같습니다.

$ ./script 5 '{a..z} {A..Z} {0..9}'

의 가치 loop는 다음과 같습니다.

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;

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.