Tất cả các kết hợp có thể có của các ký tự và số


13

Vì vậy, tôi muốn tạo ra tất cả các kết hợp có thể có của các ký tự chữ thường và chữ hoa và số có thể tạo thành chuỗi 5 ký tự.

Khả năng: a..z, A..Z và 0..9.

Có cách nào thanh lịch để làm điều này trong bash không?


1
Bạn có muốn giới hạn bản thân mình trong ASCII hoặc tập lệnh Latin không? Điều gì về dấu phụ như dấu (é, â ...)?
Stéphane Chazelas

Cảm ơn đã theo lên. Cập nhật bài gốc để làm rõ.
ardevd

Nó thực sự cần phải được trong bash? Một ngôn ngữ như Perl hoặc awk sẽ làm gì?
terdon

1
Vậy thì tại sao không gọi Perl hoặc Python từ bash? Đặc biệt với perl, nó rất dễ dàng để sử dụng nó như một lớp lót.
terdon

2
Bạn đang cố gắng học hay chỉ muốn kết quả? Trong trường hợp thứ hai, có rất nhiều chương trình thực hiện công việc như john the ripper ( john) và tương tự, sẽ cung cấp cho bạn rất nhiều khả năng.
YoMismo

Câu trả lời:


13

Đây là một giải pháp bash lấy độ dài mong muốn làm tham số (bạn sẽ làm permute 5trong trường hợp của mình):

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

Mặc dù vậy, nó rất chậm. Dám giới thiệu 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;
}

Chạy nó:

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

Các ngôn ngữ cấp cao hút vào vũ lực (về cơ bản là những gì bạn đang làm).


@ Stéphane Chazelas Cảm ơn bạn rất nhiều vì chỉnh sửa đó. Tôi đã viết bẩn, bỏ qua trích dẫn "thích hợp" vì nó không cần thiết trong trường hợp này, nhưng tôi rất biết ơn các phím tắt!
PSkocik

Tôi đã thử bashgiải pháp của bạn . Nó rất đẹp; Tôi rất thích nó. Nó hoạt động tốt trong khoảng 24 giờ hoặc lâu hơn trước khi tôi nhận thấy hệ thống của mình đã bị khóa hoàn toàn. Đã thử một cái gì đó tương tự với `python; với kết quả tương tự, mặc dù nó nhanh hơn đáng kể.
lên tiếng

7

Trong bash, bạn có thể thử:

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

nhưng điều đó sẽ mất mãi mãi và sử dụng hết bộ nhớ của bạn. Tốt nhất là sử dụng một công cụ khác như 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"}}}}}'

Coi chừng đó là 6 x 62 5 byte, vì vậy 5,496,796,992.

Bạn có thể thực hiện cùng một vòng lặp đó bash, nhưng bashlà lớp vỏ chậm nhất ở phía tây, sẽ mất hàng giờ:

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

(trên hệ thống của tôi, kết quả đầu ra ở mức 700 kiB / giây so với 20MiB / giây perltương đương).


Tôi cũng cảm thấy rằng nó sẽ thêm vào câu trả lời nếu bạn muốn thêm một cách để xuất nó thành một tệp; có thể vì nó được tạo ra nên nó không phá hủy RAM của bạn hoặc sau khi tất cả được lưu trong bộ nhớ cache
Hellreaver

2
@Hellreaver, tất cả đều ghi vào một tệp (vào thiết bị xuất chuẩn, bất kỳ tệp nào được mở; nếu chạy trong một thiết bị đầu cuối, một tệp thiết bị như /dev/pts/something; và bạn có thể thay đổi điều đó với toán tử chuyển hướng shell), không phải là bộ nhớ đầu tiên toàn bộ đầu ra trong bộ nhớ trước khi xuất nó (vào tệp mở trên thiết bị xuất chuẩn).
Stéphane Chazelas

4

Đây là một cách để làm điều đó hoàn toàn trong bash mà không phải mất 5 GB bộ nhớ:

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

Phiên bản bash này vẫn không nhanh bằng Perl nhưng nó nhanh gấp khoảng bốn lần so với năm vòng lặp lồng nhau:

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

Bạn có thể sử dụng crunch(có sẵn ít nhất trên các bản phân phối Kali).

crunch 5 5 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890

1

Chà ... thanh lịch?, Có (chỉ là một mẫu nhanh):

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

Biểu thức đầy đủ này rất có thể sẽ chặn máy tính của bạn:

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

Một tùy chọn không chặn là sử dụng một số vòng lặp:

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"

Gọi nó như:

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

Trong đó đối số đầu tiên là số lượng ký tự và thứ hai là danh sách (khoảng cách được phân tách) của các ký tự được sử dụng.

Điều đó sẽ xây dựng một biến ( loop) với tập lệnh để chạy và eval cuối cùng sẽ thực thi tập lệnh đó. Ví dụ cho:

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

Giá trị của loopsẽ là:

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;

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.