如何让这个 `echo | bc` 输出和之后的 echo 输出在同一行?

如何让这个 `echo | bc` 输出和之后的 echo 输出在同一行?

我正在制作一个用于生成随机数的程序,在生成随机数之前,我想显示有多少种组合。当我这样做时,我得到这个:

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

相关内容