好的,我的问题如下,我希望通过这个:-
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
现在我想将其中一个实例的结果添加到一个数组中,从最后 9 位数字开始索引,以接收基于纳秒时间的 4 个随机数字。
然而我似乎没有完全掌握 bash 中使用的语法来实现结果。我可以date +%s%N)/1000000
直接调用数组吗?因为我的想法是创建并清空数组,然后将结果附加到数组中,并从第 9 个数字开始索引。并将结果传递到我可以处理的第二个变量中。
只要学习将 的结果转换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))
这样,您将删除最右边的六位数字,只留下秒和毫秒。
这些并不是很随机。例如,在您的测试运行中,连续输出数字以某种程度一致的 508 增加,这以毫秒为单位与您要求的 0.5 秒非常匹配。
如果你改为,你可能会得到更多随机值保留最右边的数字,并删除前导数字,例如使用模运算符$(( ... % 1000000))
.尽管如果系统没有足够细粒度的时钟,最低数字也可能不是很随机。
如果只保留低位数字,则实际上不需要输出date
完整的秒数,而是可以只使用+%N
,除了纳秒值始终用零填充到 9 位数字,并且 Bash 将以零开头的数字视为八进制,因此例如092345678
会产生错误。在前面添加一个额外的数字可以防止这种情况发生,但添加秒值也可以防止这种情况发生。
在我的系统上,以下循环的连续迭代的值之间的差异大致在 1470000 到 1560000 ns 的范围内(约 1.5 毫秒/迭代),因此我可能不会使用超过四个最右边的数字。
#/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,它不仅限于洗牌,还可以通过重复来选择值。例如,这将打印 20 个数字,每个数字 4 位:
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
它比在 shell 中循环调用 快得多date
。您还可以使用较小的范围,例如-i 0-9
获取单位数。