日付コマンドを変数に渡しますか?

日付コマンドを変数に渡しますか?

さて、私の問題は次のとおりです。これを通過させたいと思います:-

echo $(($(date +%s%N)/1000000))

変数「a」に配列を追加することができます。次のようになります:-

a=$(($(date +%s%N)/1000000))

私がこれを行っている理由は、4 つのランダムな数字 (乱数) を使って遊びたいからです。例を示すために、この bash スクリプトを作成しました。

#!/bin/bash
for (( c=0; c<=10; c++))
do
        echo $(($(date +%s%N)/1000000))
        sleep .5
done

出力は次のようになります:- (最初の 9 桁は無視してください)

1622001937610
1622001938249
1622001938758
1622001939267
1622001939774
1622001940282
1622001940790
1622001941299
1622001941807
1622001942315
1622001942823

ここで、このインスタンスの 1 つの結果だけを配列に追加し、最後の 9 桁目からのインデックスを使用して、ナノ秒時間に基づいて 4 つのランダムな数字を受け取りたいと考えました。

しかし、結果を得るために bash 内で使用される構文を完全に理解していないようです。date +%s%N)/1000000配列を直接呼び出すことは可能でしょうか? 私の考えでは、空の配列を作成し、その結果を配列に追加し、9 番目の番号からインデックスを付けます。そして、結果を 2 番目の変数に渡して、そこから作業を進めます。

結果をdate +%s%N)/1000000変数に変換する方法を学ぶだけでも、非常に役立ちます。

ご迷惑をおかけして申し訳ありません。どうぞよろしくお願いいたします。

答え1

私の最初のアプローチは、date出力に文字列処理を使用して必要な値を取得することでした。ここでのバージョンでは数学処理(1000000で割って10000を法とする)を使用していますが、代替案をコメントに残しておきました。

#!/bin/bash
items=()

random=$(( ($(date +%s%N) / 1000000) % 10000 ))        # Second and milliseconds
# random=$( date +%s%N | grep -oP '....(?=......$)' )

items+=($random)                                       # Append value to array

echo "${items[0]}"                                     # First array value
echo "${items[-1]}"                                    # Last (most recently appended) value
declare -p items                                       # Visual inspection of array elements

答え2

あなたは${var:offset:length} パラメータ拡張構文値の部分文字列を抽出するには:

$ nanoseconds=$(date +%N)
$ printf '%s\n' "$nanoseconds" "${nanoseconds:2:4}"
785455000
5455

または、提案されているように、/dev/urandom を使用します。

$ tr -dc '[:digit:]' < /dev/urandom | fold -w 4 | head -n 10
8386
9194
3897
8790
4738
1453
4323
9021
6033
8889

bash コマンドを使用して、それを配列に読み込みますmapfile

$ mapfile -t numArray < <(tr -dc '[:digit:]' < /dev/urandom | fold -w 4 | head -n 10)
$ declare -p numArray
declare -a numArray=([0]="2851" [1]="9684" [2]="5823" [3]="5206" [4]="3208" [5]="2914" [6]="0395" [7]="4128" [8]="1876" [9]="5691")

答え3

を実行するとdate +%s%N、出力は次のようになります。

1622046533072036066
ssssssssssmmmuuunnn

右側の数字はより小さい単位を示します。( m/ u/nはミリ秒/マイクロ秒/ナノ秒を表します。)

これを 1000000 で割ると、$(( ... / 1000000))右端の 6 桁が削除され、秒とミリ秒だけが残ります。

これらはあまりランダムではありません。たとえば、テスト実行では、連続した出力番号はある程度一貫して 508 ずつ増加しますが、これはミリ秒単位では、要求した 0.5 秒とほぼ一致します。

代わりに、よりランダムな値が得られる可能性が高いでしょう保たれた右端の桁をランダムにし、先頭の桁を削除します (例: モジュロ演算子を使用) $(( ... % 1000000))。ただし、システムに十分に細かい粒度のクロックがない場合、最下位の桁もあまりランダムではない可能性があります。

date下位の桁のみを保持する場合、完全な秒数を出力する必要はなく、 のみを使用することもできます+%N。ただし、ナノ秒の値は常に 0 で埋められて 9 桁になり、Bash は 0 で始まる数字を 8 進数として扱うため、たとえば、092345678エラーが発生します。先頭に桁を追加すると、これを防ぐことができますが、秒の値を追加しても同様です。

私のシステムでは、次のループの連続した反復から得られる値の差は、およそ 1470000 ~ 1560000 ns (反復あたり約 1.5 ms) の範囲であったため、右端の数字の 4 桁以上は使用しないと思われます。

#/bin/bash
array=()
prev=$(date +%s%N)
for ((i=0; i < 100; i++)); do 
        this=$(date +%s%N)
        # diff=$(( (this - prev) % 1000000000))
        diff=$(( (this - prev) % 10000))
        printf "$prev $this %04d\n" "$diff"
        array+=("$diff")
        prev=$this
done

算術演算の代わりに、出力をdate文字列として扱い、いくつかの文字を切り取ることもできます。これにより、最後の 4 文字が残ります。

a=$(date +%N)
a=${a: -4}

また、ランダムな数字を生成する他の方法、たとえばshufGNU coreutils を使うこともできます。これはシャッフルだけでなく、繰り返しのある値を選択することもできます。たとえば、次のようにすると、それぞれ 4 桁の数字が 20 個出力されます。

shuf -i 0000-9999 -r -n 20

または、ゼロパディングを取得するためのいくつかの手順を実行します。

shuf -i 10000-19999 -r -n 20 |sed -e 's/^1//'

出力を配列に読み込むには、次のようにしますreadarray

readarray array < <(shuf -i 0000-9999 -r -n 20)

当然ながら、 は、shufの呼び出しをシェル内でループするよりも大幅に高速です。また、1 桁の数値を取得するdateなど、より狭い範囲を使用することもできます。-i 0-9

関連情報