Ok, então meu problema é o seguinte, desejo passar isso: -
echo $(($(date +%s%N)/1000000))
Em uma variável "a" pode ser adicionado a um array, algo assim: -
a=$(($(date +%s%N)/1000000))
A razão pela qual estou fazendo isso é que gostaria de ter 4 dígitos aleatórios para brincar (números aleatórios). Eu produzi este script bash para mostrar um exemplo.
#!/bin/bash
for (( c=0; c<=10; c++))
do
echo $(($(date +%s%N)/1000000))
sleep .5
done
Quais saídas: - (Ignore os primeiros 9 dígitos)
1622001937610
1622001938249
1622001938758
1622001939267
1622001939774
1622001940282
1622001940790
1622001941299
1622001941807
1622001942315
1622001942823
Agora eu queria adicionar os resultados de apenas uma instância disso em uma matriz, indexando o último nono dígito para receber 4 dígitos aleatórios com base no nano segundo tempo.
No entanto, parece que não entendi completamente a sintaxe usada no bash para obter o resultado. Eu poderia ligar date +%s%N)/1000000
diretamente para um array? Como minha ideia era criar um array vazio e depois anexar o resultado ao array e indexar a partir do 9º número. E passe o resultado para uma segunda variável a partir daí na qual eu possa trabalhar.
Apenas aprender a transformar o resultado date +%s%N)/1000000
em uma variável já seria de grande ajuda.
Desculpe ser um incômodo. Qualquer agradecimento antecipado.
Responder1
Minha abordagem inicial foi usar o processamento de strings para a date
saída obter os valores necessários. A versão aqui usa processamento matemático (dividir por 1000000, módulo 10000) mas deixei a alternativa comentada para vocês
#!/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
Responder2
Você pode usar o${var:offset:length}
sintaxe de expansão de parâmetropara extrair uma substring de um valor:
$ nanoseconds=$(date +%N)
$ printf '%s\n' "$nanoseconds" "${nanoseconds:2:4}"
785455000
5455
Ou, como sugerido, usando /dev/urandom:
$ tr -dc '[:digit:]' < /dev/urandom | fold -w 4 | head -n 10
8386
9194
3897
8790
4738
1453
4323
9021
6033
8889
Lendo isso em um array, usando o mapfile
comando 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")
Responder3
Se você executar date +%s%N
, a saída será semelhante a esta:
1622046533072036066
ssssssssssmmmuuunnn
com os dígitos da direita indicando as unidades menores. ( m
/ u
/ n
para milis/micro/nanossegundos.)
Se você dividir isso por 1.000.000, como $(( ... / 1000000))
faz, você remove os seis dígitos mais à direita, deixando apenas os segundos e milissegundos.
Isso não é muito aleatório. Por exemplo, em sua execução de teste, os números de saída consecutivos aumentam em 508 um tanto consistente, que em milissegundos corresponde aproximadamente aos 0,5 segundos solicitados.
Você provavelmente obteria mais valores aleatórios se, em vez disso,mantidoos dígitos mais à direita e eliminou os primeiros, por exemplo, com o operador de módulo, $(( ... % 1000000))
. Embora seja possível que os dígitos mais baixos também não sejam muito aleatórios, se o sistema não tiver relógios com granularidade suficientemente fina.
Se você mantiver apenas os dígitos baixos, você realmente não precisa gerar date
os segundos completos, mas pode usar apenas +%N
, exceto que o valor dos nanossegundos é sempre preenchido com zeros até 9 dígitos, e o Bash trata os números começando com zeros como octais , então, por exemplo, 092345678
produziria um erro. Adicionar um dígito extra à frente evitaria isso, mas o mesmo acontece com a adição do valor dos segundos.
No meu sistema, a diferença entre os valores de iterações consecutivas do loop a seguir estava aproximadamente na faixa de 1470000 a 1560000 ns (~ 1,5 ms/iteração), então provavelmente não usaria mais do que quatro dos dígitos mais à direita.
#/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
Em vez de aritmética, pode-se simplesmente tratar a saída date
como uma string e cortar alguns caracteres. Isso deixaria os últimos 4 caracteres:
a=$(date +%N)
a=${a: -4}
Então, novamente, poderíamos considerar outras maneiras de produzir números aleatórios, por exemplo, shuf
a partir do GNU coreutils, que não se limita apenas a embaralhar, mas também pode escolher valores com repetição. Por exemplo, isso imprimiria 20 números, 4 dígitos cada:
shuf -i 0000-9999 -r -n 20
ou com alguns aros para obter preenchimento zero:
shuf -i 10000-19999 -r -n 20 |sed -e 's/^1//'
Você pode ler a saída para um array com readarray
:
readarray array < <(shuf -i 0000-9999 -r -n 20)
Não é de surpreender shuf
que seja terrivelmente mais rápido do que fazer um loop no shell por meio de chamadas para date
. Você também pode usar um intervalo menor, por exemplo, -i 0-9
para obter números de um único dígito.