Use $RANDOM. Geralmente é útil em combinação com a aritmética simples do shell. Por exemplo, para gerar um número aleatório entre 1 e 10 (inclusive):
$ echo $((1+ RANDOM %10))3
O gerador atual está dentro variables.c, a função brand(). As versões mais antigas eram um gerador linear simples. A versão 4.0 de bashusa um gerador com uma citação de um artigo de 1985, o que presumivelmente significa que é uma fonte decente de números pseudo-aleatórios. Eu não o usaria para uma simulação (e certamente não para criptografia), mas provavelmente é adequado para tarefas básicas de script.
Se você estiver fazendo algo que exija números aleatórios sérios, poderá usar /dev/randomou /dev/urandomse estiverem disponíveis:
Tenha cuidado aqui. Enquanto isso é bom em uma pitada, fazer aritmética em números aleatórios pode afetar drasticamente a aleatoriedade do seu resultado. no caso de $RANDOM % 10, 8 e 9 são mensuráveis (embora marginalmente) menos prováveis que 0-7, mesmo que $RANDOMseja uma fonte robusta de dados aleatórios.
Dimo414
3
@ dimo414 Estou curioso para "marginalmente", você tem uma fonte onde eu possa descobrir mais sobre isso?
PascalVKooten
58
Ao modular sua entrada aleatória, você está " furando " os resultados. Como $RANDOMo intervalo é 0-32767o número 0- 7mapeie para 3277diferentes entradas possíveis, mas 8e 9só pode ser produzido de 3276maneiras diferentes (porque 32768e 32769não são possíveis). Esse é um problema menor para hacks rápidos, mas significa que o resultado não é uniformemente aleatório. Bibliotecas aleatórias, como as de Java Random, oferecem funções para retornar adequadamente um número aleatório uniforme no intervalo especificado, em vez de simplesmente modificar um número não divisível.
Dimo414 26/05
1
@JFSebastian é verdade - o problema com o módulo é que ele pode quebrar a uniformidade de qualquer RNG, não apenas PRNGs ruins, mas obrigado por chamar isso.
precisa saber é o seguinte
14
Apenas por contexto, o escaneamento básico para% 10 significa 8 e 9 são cerca de 0,03% menos prováveis de ocorrer do que 0–7. Se o seu script shell requer números aleatórios uniformes mais precisos do que isso, use todos os meios de um mecanismo mais complexo e adequado.
$RANDOM é uma função Bash interna (não uma constante) que retorna um número inteiro pseudoaleatório no intervalo de 0 a 32767. Não deve ser usada para gerar uma chave de criptografia.
@JinKwon 32767é 2^16 / 2 - 1o limite superior para um número inteiro assinado de 16 bits.
10137 Jeffrey Martinez
@JinKwon, você poderia esclarecer por que não diz que é 2^15 - 1? É equivalente, então estou curioso para saber se há algum contexto em falta?
Brett Holman
11
@BrettHolman Acho que ele estava tentando apontar a parte "assinada" do inteiro assinado de 16 bits. 2 ^ 16 valores, divididos ao meio para entradas positivas e negativas.
Cody
Esta resposta não responde à pergunta.
brat
48
Você também pode usar shuf (disponível em coreutils).
Como você passa em Vars no final do intervalo? Eu consegui:shuf -i 1-10 -n 1: syntax error in expression (error token is "1-10 -n 1")
dat tutbrus
1
Adicionar um $varao invés do fim gama, como este:var=100 && shuf -i 1-${var} -n 1
knipwim
2
Prefiro essa opção, pois é fácil gerar N números aleatórios -n. Por exemplo, gere 5 números aleatórios entre 1 e 100 :shuf -i 1-100 -n 5
aerijman 14/01
Tanto quanto eu entendo os números não são aleatórios. Se você especificar shuf -i 1-10 -n 10, obterá todos os números de 1 a 10, exatamente um. Se você especificar -n 15, ainda receberá apenas esses 10 números exatamente uma vez. Isso é realmente apenas baralhar, não gerar números aleatórios.
radlan
Para obter números aleatórios com a substituição: -r
Geoffrey Anderson
36
Tente isso no seu shell:
$ od -A n -t d -N 1/dev/urandom
Aqui, -t despecifica que o formato de saída deve ser assinado como decimal; -N 1diz para ler um byte de /dev/urandom.
+1 você sabe, no começo eu pensei por que você iria querer fazer assim, mas na verdade eu gosto bastante.
zelanix
1
Obrigado por fornecer uma solução que inclui a propagação. Não encontrei em lugar algum!
so.very.tired
2
+1 para semear. Vale a pena mencionar que srand()a semente é o tempo atual da CPU. Se você precisar especificar uma semente específica, para que o RNG possa ser duplicado, use srand(x)onde xestá a semente. Além disso, citado no manual de funções numéricas do GNU awk, "diferentes implementações do awk usam diferentes geradores de números aleatórios internamente". O resultado é que, se você estiver interessado em gerar distribuição estatística, espere pequenas variações passando de um tempo de execução para outro em uma plataforma diferente (todas em execução awkou gawk).
24419 Cbhihe
18
Há $ ALEATÓRIO. Não sei exatamente como isso funciona. Mas funciona. Para testar, você pode fazer:
$ RANDOM está no intervalo de 0 a 32767. Você terminará com mais números que começam com 1, 2 ou 3 do que com 4-9. Se você estiver de acordo com uma distribuição desequilibrada, isso funcionará bem.
precisa saber é o seguinte
2
@ jbo5112 você está totalmente certo, que tal exibir o último dígito? eco $ {RANDOM: 0-1} para um dígito, $ {RANDOM: 0-2} para dois dígitos ...?
fraff
4
Se você usar o (s) último (s) dígito (s), ele será bastante bom, mas incluirá zeros e zeros. Em um único dígito, 0-7 ocorrerá 0,03% com mais frequência que 8-9. Em 2 dígitos, 0-67 ocorrerá 0,3% mais frequentemente que 68-99. Se você precisar de uma distribuição de números aleatórios tão boa, espero que você não esteja usando o bash. Com o original: ${RANDOM:0:1}tem 67,8% de chance de fornecer 1 ou 2, ${RANDOM:0:2}apenas 0,03% de chance de fornecer um número de dígito único (deve ser 1%) e ambos têm 0,003% de chance de fornecer 0 Ainda existem casos de uso em que isso é bom (por exemplo, entrada não consistente).
Meu mal, não leu a página de manual corretamente. $RANDOMsó vai de 0 a 32767. Deveria ter dito "Número aleatório principalmente entre 1 e 3, com alguns alas";)
David Newcomb
1
O que? Ainda estará entre 0 e 9, embora 8 e 9 tenham uma probabilidade ligeiramente menor de ocorrer que 0 a 7, conforme mencionado em outra resposta.
Kini #
6
Se você estiver usando um sistema Linux, poderá obter um número aleatório de / dev / random ou / dev / urandom. Tenha cuidado / dev / random irá bloquear se não houver números aleatórios suficientes disponíveis. Se você precisar de velocidade acima da aleatoriedade, use / dev / urandom.
Esses "arquivos" serão preenchidos com números aleatórios gerados pelo sistema operacional. Depende da implementação de / dev / random no seu sistema se você obtiver números verdadeiros ou pseudo-aleatórios. Números aleatórios verdadeiros são gerados com a ajuda do ruído coletado de drivers de dispositivos como mouse, disco rígido e rede.
Você pode obter números aleatórios do arquivo com dd
Eu peguei algumas dessas idéias e criei uma função que deveria ser executada rapidamente se forem necessários muitos números aleatórios.
ligar odé caro se você precisar de muitos números aleatórios. Em vez disso, chamo uma vez e armazeno 1024 números aleatórios em / dev / urandom. Quandorand é chamado, o último número aleatório é retornado e redimensionado. É então removido do cache. Quando o cache está vazio, outros 1024 números aleatórios são lidos.
Exemplo:
rand 10; echo $RET
Retorna um número aleatório no RET entre 0 e 9, inclusive.
declare -ia RANDCACHE
declare -i RET RAWRAND=$(((1<<32)-1))function rand(){# pick a random number from 0 to N-1. Max N is 2^32local-i N=$1
[[ ${#RANDCACHE[*]}-eq 0]]&&{ RANDCACHE=( $(od -An-tu4 -N1024 /dev/urandom));}# refill cache
RET=$(((RANDCACHE[-1]*N+1)/RAWRAND ))# pull last random number and scale
unset RANDCACHE[${#RANDCACHE[*]}-1]# pop read random number};# test by generating a lot of random numbers, then effectively place them in bins and count how many are in each bin.
declare -i c; declare -ia BIN
for(( c=0; c<100000; c++));do
rand 10
BIN[RET]+=1# add to bin to check distributiondonefor(( c=0; c<10; c++));do
printf "%d %d\n" $c ${BIN[c]}done
UPDATE: Isso não funciona tão bem para todos os N. Ele também desperdiça bits aleatórios se usado com N. pequeno. Observando que (nesse caso) um número aleatório de 32 bits tem entropia suficiente para 9 números aleatórios entre 0 e 9 (10 * 9 = 1.000.000.000 <= 2 * 32), podemos extrair vários números aleatórios de cada 32 valor fonte aleatório.
#!/bin/bash
declare -ia RCACHE
declare -i RET # return value
declare -i ENT=2# keep track of unused entropy as 2^(entropy)
declare -i RND=RANDOM%ENT # a store for unused entropy - start with 1 bit
declare -i BYTES=4# size of unsigned random bytes returned by od
declare -i BITS=8*BYTES # size of random data returned by od in bits
declare -i CACHE=16# number of random numbers to cache
declare -i MAX=2**BITS # quantum of entropy per cached random number
declare -i c
function rand(){# pick a random number from 0 to 2^BITS-1[[ ${#RCACHE[*]}-eq 0]]&&{ RCACHE=( $(od -An-tu$BYTES -N$CACHE /dev/urandom));}# refill cache - could use /dev/random if CACHE is small
RET=${RCACHE[-1]}# pull last random number and scale
unset RCACHE[${#RCACHE[*]}-1]# pop read random number};function randBetween(){local-i N=$1
[[ ENT -lt N ]]&&{# not enough entropy to supply ln(N)/ln(2) bits
rand; RND=RET # get more random bits
ENT=MAX # reset entropy}
RET=RND%N # random number to return
RND=RND/N # remaining randomness
ENT=ENT/N # remaining entropy};
declare -ia BIN
for(( c=0; c<100000; c++));do
randBetween 10
BIN[RET]+=1donefor c in ${BIN[*]};do
echo $c
done
Eu tentei isso - foram necessários 10 segundos de 100% da CPU e, em seguida, foram impressos 10 números que não pareciam aleatórios.
Carlo Wood
Eu me lembro agora. Este código gera 100.000 números aleatórios. Ele coloca cada um em um 'bin' para ver como é aleatório. Existem 10 caixas. Esses números devem ser semelhantes se cada número aleatório entre 0 e 9 for igualmente provável. Se você deseja imprimir cada número, echo $ RET após RANDBETWEEN 10.
philcolbourn
od -An -tu4 -N40 /dev/urandomirá gerar 10 números inteiros aleatórios e não assinados, separados por espaços em branco. você pode armazená-lo em uma matriz e usá-lo posteriormente. seu código parece ser um exagero.
Ali
@ Ali, OP não especificou que eles queriam 32 bits nem qualquer outro número aleatório de tamanho. Eu e alguns outros interpretamos essa pergunta como fornecendo um número aleatório dentro de um intervalo. Minha função rand atinge esse objetivo e também reduz a perda de entropia que, se esgotada, causa o bloqueio de programas. od on / dev / urandom retorna apenas números aleatórios de 2 ^ N bits e o OP precisaria armazenar vários valores em uma matriz, extraindo-os sequencialmente dessa matriz e reabastecendo essa matriz. Talvez você possa codificar isso como resposta e lidar com outros intervalos de números aleatórios?
#
@philcolbourn, você está certo sobre o OP não especificar que tipo de número aleatório ele quer e perdeu minha atenção. Mas ele apenas perguntou: "Como gerar um número aleatório no bash?". O que quero dizer é que ele só pediu um número aleatório. Embora esse crítico se aplique ao meu comentário anterior (gerando 10 números aleatórios) também.
Ali
5
Ler arquivos especiais de caracteres / dev / random ou / dev / urandom é o caminho a percorrer.
Esses dispositivos retornam números verdadeiramente aleatórios quando lidos e foram projetados para ajudar o software aplicativo a escolher chaves seguras para criptografia. Esses números aleatórios são extraídos de um pool de entropia que é contribuído por vários eventos aleatórios. {LDD3, Jonathan Corbet, Alessandro Rubini e Greg Kroah-Hartman]
Esses dois arquivos são uma interface para a randomização do kernel, em particular
void get_random_bytes_arch(void* buf, int nbytes)
que extrai bytes verdadeiramente aleatórios do hardware, se essa função é implementada pelo hardware (geralmente é), ou extrai do pool de entropia (composto por tempos entre eventos como interrupções de mouse e teclado e outras interrupções registradas no SA_SAMPLE_RANDOM).
dd if=/dev/urandom count=4 bs=1| od -t d
Isso funciona, mas grava saída desnecessária de ddpara stdout. O comando abaixo fornece apenas o número inteiro que eu preciso. Posso até obter um número especificado de bits aleatórios, conforme necessário, ajustando a máscara de bits dada à expansão aritmética:
Para um número aleatório criptograficamente seguro, você precisa ler em / dev / urandom ou usar as bibliotecas Crypt :: Random.
kh
3
Talvez eu esteja um pouco atrasado, mas e quanto a usar jotpara gerar um número aleatório dentro de um intervalo no Bash?
jot -r -p 3101
Isso gera um -rnúmero aleatório ( ) com precisão de 3 casas decimais ( -p). Nesse caso específico, você obterá um número entre 0 e 1 ( 1 0 1). Você também pode imprimir dados seqüenciais. A fonte do número aleatório, de acordo com o manual, é:
Os números aleatórios são obtidos através do arc4random (3) quando nenhuma semente é especificada e através do aleatório (3) quando uma semente é fornecida.
Respostas:
Use
$RANDOM
. Geralmente é útil em combinação com a aritmética simples do shell. Por exemplo, para gerar um número aleatório entre 1 e 10 (inclusive):O gerador atual está dentro
variables.c
, a funçãobrand()
. As versões mais antigas eram um gerador linear simples. A versão 4.0 debash
usa um gerador com uma citação de um artigo de 1985, o que presumivelmente significa que é uma fonte decente de números pseudo-aleatórios. Eu não o usaria para uma simulação (e certamente não para criptografia), mas provavelmente é adequado para tarefas básicas de script.Se você estiver fazendo algo que exija números aleatórios sérios, poderá usar
/dev/random
ou/dev/urandom
se estiverem disponíveis:fonte
$RANDOM % 10
, 8 e 9 são mensuráveis (embora marginalmente) menos prováveis que 0-7, mesmo que$RANDOM
seja uma fonte robusta de dados aleatórios.$RANDOM
o intervalo é0-32767
o número0
-7
mapeie para3277
diferentes entradas possíveis, mas8
e9
só pode ser produzido de3276
maneiras diferentes (porque32768
e32769
não são possíveis). Esse é um problema menor para hacks rápidos, mas significa que o resultado não é uniformemente aleatório. Bibliotecas aleatórias, como as de JavaRandom
, oferecem funções para retornar adequadamente um número aleatório uniforme no intervalo especificado, em vez de simplesmente modificar um número não divisível.Por favor veja
$RANDOM
:fonte
32767
tem algum significado especial?32767
é2^16 / 2 - 1
o limite superior para um número inteiro assinado de 16 bits.2^15 - 1
? É equivalente, então estou curioso para saber se há algum contexto em falta?Você também pode usar shuf (disponível em coreutils).
fonte
shuf -i 1-10 -n 1: syntax error in expression (error token is "1-10 -n 1")
$var
ao invés do fim gama, como este:var=100 && shuf -i 1-${var} -n 1
-n
. Por exemplo, gere 5 números aleatórios entre 1 e 100 :shuf -i 1-100 -n 5
shuf -i 1-10 -n 10
, obterá todos os números de 1 a 10, exatamente um. Se você especificar-n 15
, ainda receberá apenas esses 10 números exatamente uma vez. Isso é realmente apenas baralhar, não gerar números aleatórios.Tente isso no seu shell:
Aqui,
-t d
especifica que o formato de saída deve ser assinado como decimal;-N 1
diz para ler um byte de/dev/urandom
.fonte
od -A n -t d -N 1 /dev/urandom |tr -d ' '
você também pode obter um número aleatório do awk
fonte
srand()
a semente é o tempo atual da CPU. Se você precisar especificar uma semente específica, para que o RNG possa ser duplicado, usesrand(x)
ondex
está a semente. Além disso, citado no manual de funções numéricas do GNU awk, "diferentes implementações do awk usam diferentes geradores de números aleatórios internamente". O resultado é que, se você estiver interessado em gerar distribuição estatística, espere pequenas variações passando de um tempo de execução para outro em uma plataforma diferente (todas em execuçãoawk
ougawk
).Há $ ALEATÓRIO. Não sei exatamente como isso funciona. Mas funciona. Para testar, você pode fazer:
fonte
Eu gosto deste truque:
...
fonte
${RANDOM:0:1}
tem 67,8% de chance de fornecer 1 ou 2,${RANDOM:0:2}
apenas 0,03% de chance de fornecer um número de dígito único (deve ser 1%) e ambos têm 0,003% de chance de fornecer 0 Ainda existem casos de uso em que isso é bom (por exemplo, entrada não consistente).Número aleatório entre 0 e 9, inclusive.
fonte
$RANDOM
só vai de 0 a 32767. Deveria ter dito "Número aleatório principalmente entre 1 e 3, com alguns alas";)Se você estiver usando um sistema Linux, poderá obter um número aleatório de / dev / random ou / dev / urandom. Tenha cuidado / dev / random irá bloquear se não houver números aleatórios suficientes disponíveis. Se você precisar de velocidade acima da aleatoriedade, use / dev / urandom.
Esses "arquivos" serão preenchidos com números aleatórios gerados pelo sistema operacional. Depende da implementação de / dev / random no seu sistema se você obtiver números verdadeiros ou pseudo-aleatórios. Números aleatórios verdadeiros são gerados com a ajuda do ruído coletado de drivers de dispositivos como mouse, disco rígido e rede.
Você pode obter números aleatórios do arquivo com dd
fonte
Eu peguei algumas dessas idéias e criei uma função que deveria ser executada rapidamente se forem necessários muitos números aleatórios.
ligar
od
é caro se você precisar de muitos números aleatórios. Em vez disso, chamo uma vez e armazeno 1024 números aleatórios em / dev / urandom. Quandorand
é chamado, o último número aleatório é retornado e redimensionado. É então removido do cache. Quando o cache está vazio, outros 1024 números aleatórios são lidos.Exemplo:
Retorna um número aleatório no RET entre 0 e 9, inclusive.
UPDATE: Isso não funciona tão bem para todos os N. Ele também desperdiça bits aleatórios se usado com N. pequeno. Observando que (nesse caso) um número aleatório de 32 bits tem entropia suficiente para 9 números aleatórios entre 0 e 9 (10 * 9 = 1.000.000.000 <= 2 * 32), podemos extrair vários números aleatórios de cada 32 valor fonte aleatório.
fonte
od -An -tu4 -N40 /dev/urandom
irá gerar 10 números inteiros aleatórios e não assinados, separados por espaços em branco. você pode armazená-lo em uma matriz e usá-lo posteriormente. seu código parece ser um exagero.Ler arquivos especiais de caracteres / dev / random ou / dev / urandom é o caminho a percorrer.
Esses dois arquivos são uma interface para a randomização do kernel, em particular
que extrai bytes verdadeiramente aleatórios do hardware, se essa função é implementada pelo hardware (geralmente é), ou extrai do pool de entropia (composto por tempos entre eventos como interrupções de mouse e teclado e outras interrupções registradas no SA_SAMPLE_RANDOM).
Isso funciona, mas grava saída desnecessária de
dd
para stdout. O comando abaixo fornece apenas o número inteiro que eu preciso. Posso até obter um número especificado de bits aleatórios, conforme necessário, ajustando a máscara de bits dada à expansão aritmética:fonte
A respeito:
fonte
Talvez eu esteja um pouco atrasado, mas e quanto a usar
jot
para gerar um número aleatório dentro de um intervalo no Bash?Isso gera um
-r
número aleatório ( ) com precisão de 3 casas decimais (-p
). Nesse caso específico, você obterá um número entre 0 e 1 (1 0 1
). Você também pode imprimir dados seqüenciais. A fonte do número aleatório, de acordo com o manual, é:fonte
Com base nas ótimas respostas de @Nelson, @Barun e @Robert, aqui está um script Bash que gera números aleatórios.
/dev/urandom
que é muito melhor do que o built-in do Bash$RANDOM
fonte
Gere um número aleatório no intervalo de 0 a n (número inteiro assinado de 16 bits). Conjunto de resultados na variável $ RAND. Por exemplo:
fonte
Ramificação aleatória de um programa ou sim / não; 1/0; saída verdadeira / falsa:
de se você tem preguiça de lembrar 16383:
fonte