所以我想生成所有可能的小写和大写字符以及数字的组合,以组成 5 个字符的字符串。
可能性:a..z、A..Z 和 0..9。
在 bash 中是否有任何优雅的方法可以做到这一点?
答案1
这是一个 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>
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
高级语言在暴力破解方面很糟糕(这基本上就是你正在做的事情)。
答案2
在 中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
作为西方最慢的 shell,这将需要几个小时:
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
(在我的系统上,输出速度为 700 kiB/s,而同等系统的输出速度为 20MiB/s perl
)。
答案3
您可以使用crunch
(至少在 Kali 发行版上可用)。
crunch 5 5 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890
答案4
Gnu Parallel 可以进行组合,请参阅https://www.gnu.org/software/parallel/像这样的东西:
parallel echo ::: {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}