この `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.

最初にすべきことは、printf2番目のパラメータを試すことです。${2##*[!0-9]*}数値以外の文字が含まれている場合は、パラメータ拡張が行われ、nullとしてレンダリングされます。%digit値の算術拡張が先行し、完全な実行ループが発生します。この算術拡張は次のとおりです。進行中。実際、関数全体はprintf現在のシェルの観点から見た説明にすぎません。

しかし、$((数学拡張では、))これは$(命令の置き換え)に過ぎず、それ以上ではありません。我々は何も提供しません。ただそれだけです$(($()))

コマンド置換のサブシェルを除外すると、ループを実行して出力を収集します。私たちの出力は最終的に実行可能な算術式にまとめられました。

$aループでは、常に各ループの先頭に最初の文字を置きます$x。次に、$aいくつかのパターンに基づいて現在の値のヘッダーを確認しますcase。そのうちの最初のものは次のとおりです。

([a-z]-["$x"-z]*|[A-Z]-["$x"-Z]*)

$aここでは、2回保存した最初の文字を使用します$x。まず、私たちのモデルを比較する議論です。しかし、2番目に、これは3番目の$a文字のリミッタです。これは、3番目の文字がアルファベットの範囲内に収まるだけでなく、1$a番目の文字以上であることを保証します。無効な範囲なので、z-aテストに使用した場合は一致しません。$x

このパターンが一致すると、ヘッダーから2つの文字を削除して、各合計のASCII数値を印刷します$x$a$a

このように:

printf '(%d-%d+1)+' "'$x" "'$a"

...これは最終算術で括弧サブ式になり、範囲間の距離を計算します。

数字にも同じことを行います。

 ([0-9]-["$x"-9]*)

$aこの場合も頭を切る。数字の数学は少し異なります。負の数を取得します。$aの最初の3文字はに保存されます$xx=4-9

だから我々は以下を印刷します:

printf "$((-($x)+1))+"

担当者の場合$a そうだ最初の2つのテストでまだ失敗する範囲と同様に、(?-*)パターンと一致し、上位2文字を削除しecho 2+て再度繰り返します。

パターンまで設定すると、可能な範囲で最初の項目が一致するまで(?*)最初から$aすべてが削除されます$a。成功した場合はループを繰り返し繰り返し、差分を分割しますが、残りの部分に可能な範囲一致がない場合は、基本的にここですべての権限とエコーを$a消費するため、ループを終了します。$a${#a}+

まあ、私たちはあきらめません。しかし、$a- ループの上部が空の状態に戻されるまで、ループは終了しません。これが発生した場合は、出力! echo 0に書き込まれた最後の文字列を実行します。

したがって、現在のシェルに戻って数学拡張のすべての内容をprintと評価すると、出力"$((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

関連情報