将日期命令传递给变量?

将日期命令传递给变量?

好的,我的问题如下,我希望通过这个:-

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获取单位数。

相关内容