Передача команды date в переменную?

Передача команды date в переменную?

Итак, моя проблема заключается в следующем. Я хочу передать это:

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

Считываем это в массив, используя mapfileкоманду bash:

$ 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 обрабатывает числа, начинающиеся с нулей, как восьмеричные, поэтому eg 092345678приведет к ошибке. Добавление дополнительной цифры в начало предотвратит это, но то же самое делает и добавление значения секунд.

В моей системе разница между значениями из последовательных итераций следующего цикла составляла примерно от 1470000 до 1560000 нс (~ 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что это ужасно быстрее, чем цикл в оболочке по вызовам date. Вы также можете использовать меньший диапазон, например, -i 0-9для получения однозначных чисел.

Связанный контент