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

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

さて、私の質問は次のとおりです。この質問に合格したい。

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

これは、次のように変数 "a" に追加できます。

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

これを行う理由は、4つの乱数(Random Number)を使いたいからです。例を示すために、この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

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

1622046533072036066
ssssssssssmmmuuunnn

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

このように1000000で割ると$(( ... / 1000000))一番右の6桁を取り除き、秒とミリ秒だけ残ります。

これは非常にランダムではありません。たとえば、テスト実行では、連続出力数はやや一貫した508増加します。これは、ミリ秒単位で必要な0.5秒とほぼ一致します。

次に変更すると、より多くのランダムな値が得られます。予約する一番右の数字と先頭の数字はモジュロ演算子を使用して削除されます$(( ... % 1000000))。ただし、システムに十分に細分化された時計がない場合、最も低い数字はランダムではない可能性があります。

date低い数字だけを維持する場合は、実際には秒数全体を出力する必要はありませんが、単に使用するだけです+%N。ただし、ナノ秒の値は常に0から9桁まで埋められ、Bashは0から始まる数字を次のように処理します。 8進数なので092345678エラーが発生します。前に数字を追加することでこれを防ぐことができますが、秒値を追加するとそれを防ぐことができます。

私のシステムでは、次のループの連続反復の値の差が約1470000〜1560000ns(約1.5ms /繰り返し)の範囲であるため、最も右側の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}

shufその後、再混合に限定されず、繰り返しを通じて値を選択することができる、GNU 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シェルで繰り返すよりもはるかに高速ですdate-i 0-9単位数の取得など、より小さい範囲を使用することもできます。

関連情報