したがって、5文字の文字列を構成できる小文字と大文字のすべての可能な組み合わせを生成したいと思います。
可能性:a..z、A..Zおよび0..9。
bashでこれを行うエレガントな方法はありますか?
perl、ワンライナーとして使用するのは非常に簡単です。
john)などの仕事をするプログラムがたくさんあります。
したがって、5文字の文字列を構成できる小文字と大文字のすべての可能な組み合わせを生成したいと思います。
可能性:a..z、A..Zおよび0..9。
bashでこれを行うエレガントな方法はありますか?
perl、ワンライナーとして使用するのは非常に簡単です。
john)などの仕事をするプログラムがたくさんあります。
回答:
パラメーターとして希望の長さを取る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
高レベルの言語は、総当たり攻撃(基本的にはあなたがしていることです)を嫌います。
bash解決策を試しました。それは非常にうれしいです; それは大好きです。私のシステムが完全にロックされていることに気付く前に、それは約24時間ほどうまく機能しました。`pythonで似たようなことを試みました。同様の結果が得られましたが、かなり高速でした。
では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
(私のシステムでは、perl同等の20MiB / sではなく700kiB / sで出力します)。
/dev/pts/something、シェルリダイレクト演算子で変更できます)、メモリではなく、最初のビルド(stdoutで開いているファイルに)出力する前に、メモリ内の出力全体。
これは、5 GBのメモリを浪費することなく、純粋に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
使用できますcrunch(少なくともKaliディストリビューションで利用可能です)。
crunch 5 5 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890
まあ...エレガント?、はい(ちょうど速いサンプル):
eval echo $(printf "%s" '{{a..z},{A..Z},{0..9}}'{,,} )
この完全な表現は、おそらくコンピューターをブロックします。
eval echo $(printf "%s" '{{a..z},{A..Z},{0..9}}'{,,,,} )
ノンブロッキングオプションの1つは、複数のループを使用することです。
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}'
ここで、最初の引数は文字数で、2番目は使用する文字のリスト(スペース区切り)です。
これloopにより、実行するスクリプトで変数()が構築され、最後のevalがそのスクリプトを実行します。例えば:
$ ./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;
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}