我正在制作一个用于生成随机数的程序,在生成随机数之前,我想显示有多少种组合。当我这样做时,我得到这个:
64k@conroe$ bash random A-Za-z0-9 3
238328
possible combinations
CG1
我希望“可能的组合”与“238328”在同一行,所以我得到
238328 possible combinations
这是该部分的代码:
if [ $1 == 'A-Z' ] || [ $1 == 'a-z' ]
then
echo "26^$2" | bc
elif [ $1 == 'A-Za-z' ] || [ $1 == 'a-zA-Z' ]
then
echo "52^$2" | bc
elif [ $1 == 'A-Z0-9' ] || [ $1 == 'a-z0-9' ]
then
echo "36^$2" | bc
elif [ $1 == 'A-Za-z0-9' ] ||[ $1 == 'a-zA-Z0-9' ]
then
echo "62^$2" | bc
else
echo "${#$1}^$2" | bc
fi
echo "possible combinations"
如果有什么方法可以缩短这个时间,我很乐意得到建议。我对 bash 脚本还比较陌生。
另外,有没有可能的方法让 输出echo | bc
以逗号分隔的数字?有些数字可能变得非常大,即random A-Za-z0-9 10
可能的组合数量为839299365868340224
。我希望用逗号分隔,以便显示839,299,365,868,340,224
。完整代码:
if [ $1 == 'A-Z' ] || [ $1 == 'a-z' ]
then
echo "26^$2" | bc
elif [ $1 == 'A-Za-z' ] || [ $1 == 'a-zA-Z' ]
then
echo "52^$2" | bc
elif [ $1 == 'A-Z0-9' ] || [ $1 == 'a-z0-9' ]
then
echo "36^$2" | bc
elif [ $1 == 'A-Za-z0-9' ] ||[ $1 == 'a-zA-Z0-9' ]
then
echo "62^$2" | bc
else
echo "${#$1}^$2" | bc
fi
echo "possible combinations"
if [ $# == 2 ]
then
< /dev/urandom env LC_CTYPE=C tr -dc $1 | head -c $2 | while read -n 1 x
do
printf "\e[1;36m$x"
sleep 0.03
done
echo -e '\033[0m'
exit 0
exit 1
elif [ $# == 3 ]
then
for (( c=1; c<=$3; c++ ))
do {
< /dev/urandom env LC_CTYPE=C tr -dc $1 | head -c $2 | while read -n 1 x
do
printf "\e[0;33m$x"
sleep 0.03
done
echo -e '\033[0m'
}
done
exit 1
fi
答案1
如果没有别的事,你需要一份case
声明。
random(){
printf "%d^${2##*[!0-9]*}\n" "$(($(
export LC_ALL=C; a=$1
while x=${a%"${a#?}"} s=
case $a in
([a-z]-["$x"-z]*|[A-Z]-["$x"-Z]*)
a=${a#??} s=?
printf '(%d-%d+1)+' "'$a" "'$x";;
([0-9]-["$x"-9]*)
x=${a%"${a#???}"} a=${a#"$x"}
printf "$((-($x)+1))+";;
(?-*) a=${a#??}
echo 2+;;
(?*) x=${a%%[A-Za-z0-9]-*}
a=${a#"$x"}
echo "${#x}+";;
(*) ! echo 0 ;;esac
do a=${a#$s} ; done
)))" | bc| sed 's/$/ possibilities./
/^1 /s/....$/y./'
}
好吧,我必须道歉 - 我现在才意识到我认为的 char 类是文字参数字符串 - 并且您正在解析它们。现在我明白你在说什么了。我刚刚让它工作了 - 它实际上会做范围,并且您可以处理任何类型的字符 - 因为它会计算差异。
{ random A 1 #1 char and 1
random AB 1 #2 chars and 1
random a-Z 1 #3 chars because the range is invalid and 1
random aa-c 1 #4 chars: aabc and 1
random a-c 2 #3 chars: abc and 2
random aa-z 3) #27 chars:aa-z and 3
}
输出
1 possibility.
2 possibilities.
3 possibilities.
4 possibilities.
9 possibilities.
19683 possibilities.
要做的第一件事是我们尝试printf
我们的第二个参数 -${2##*[!0-9]*}
如果它包含任何非数字字符,它会经历参数扩展以将其呈现为 null - 前面是%d
算术扩展的 igit 值,整个运行循环发生在该算术扩展中。其实整个函数printf
从当前shell的角度来看就是一条语句。
但在$((
数学扩展中))
是一个$(
命令替换)
- 仅此而已。我们没有提供任何数字 - 它只是$(($()))
。
除了命令替换中的子 shell 运行我们的循环并收集我们的输出。我们的输出最终加起来就是一个可行的算术表达式。
在循环中,我们总是将$a
的第一个字符放在$x
每个循环的顶部。接下来,我们$a
根据某些模式检查当前值的头部case
。其中第一个看起来像这样:
([a-z]-["$x"-z]*|[A-Z]-["$x"-Z]*)
这里我们使用了$a
我们保存的第一个字符$x
两次。首先,它是我们比较我们的模式的论点。但其次,它是 的$a
第三个字符的限制器 - 它确保第三个字符不仅适合字母范围,而且还大于或等于 的$a
第一个字符。因为是一个无效的范围,当我们用来测试z-a
时不匹配。$x
如果我们匹配这个模式,我们会在从头部删除两个字符后打印每个$x
和的 ascii 数字值。$a
$a
像这样:
printf '(%d-%d+1)+' "'$x" "'$a"
...这成为我们最终算术中的括号子表达式,并计算出我们范围之间的距离。
我们对数字做同样的事情:
([0-9]-["$x"-9]*)
$a
在这种情况下我们也会把头砍掉。数字的数学计算有点不同——我们得到负数。$a
的前三个字符保存在$x
,如x=4-9
.
所以我们打印:
printf "$((-($x)+1))+"
如果该负责人$a
看起来就像一个范围,但仍然未能通过前两个测试,因此与我们的(?-*)
模式匹配,然后我们将删除顶部两个字符 ,echo 2+
并再次循环。
如果我们将其设置为与模式一样远,(?*)
那么我们将从头开始删除$a
所有内容,直到 中第一个出现的可能范围匹配$a
。如果我们成功了,我们将继续循环并分割差异,但如果 的其余部分没有可能的范围匹配$a
,我们将退出循环,因为我们基本上会消耗$a
这里的所有权利和 echo 。${#a}+
好吧,我们不会放弃它然而- 循环永远不会退出,直到$a
被发送回循环顶部为空。当发生这种情况时,我们会执行! echo 0
写入输出的最后一个字符串。
因此,返回到当前 shell 并评估数学扩展中的所有内容以打印"$((subshell_math))^$2"
,bc
其输出通过管道传输到sed
将字符串附加possibles.
到其输出。
这就是它的工作原理。
答案2
我会使用反引号保存输出,然后您可以使用 printf 对其进行格式化:
if [ $1 == 'A-Z' ] || [ $1 == 'a-z' ]
then
combinations=`echo "26^$2" | bc`
elif [ $1 == 'A-Za-z' ] || [ $1 == 'a-zA-Z' ]
combinations=`echo "52^$2" | bc`
# ... and so on ...
fi
printf "%'.0f possible combinations\n" $combinations
就清理代码而言,如果不知道稍后如何使用参数,会有点困难,但我要改变的一件事是一次检查您期望的部分,而不是寻找所有可能的排列。
#!/bin/bash
chars='0'
if [[ $1 == *"0-9"* ]]; then
chars="$chars+10"
fi
if [[ $1 == *"a-z"* ]]; then
chars="$chars+26"
fi
if [[ $1 == *"A-Z"* ]]; then
chars="$chars+26"
fi
combinations=`echo "($chars)^$2" | bc`
printf "%'.0f possible combinations\n" $combinations