Eu quero uma maneira de executar um comando aleatoriamente, digamos 1 em cada 10 vezes. Existe um coreutil interno ou GNU para fazer isso, idealmente algo como:
chance 10 && do_stuff
onde do_stuff
é executado apenas 1 em 10 vezes? Eu sei que poderia escrever um script, mas parece uma coisa bastante simples e fiquei pensando se existe uma maneira definida.
Respostas:
In
ksh
, Bash, Zsh, Yash ou BusyBoxsh
:A
RANDOM
variável especial dos shells Korn, Bash, Yash, Z e BusyBox produz um valor inteiro decimal pseudo-aleatório entre 0 e 32767 toda vez que é avaliada; portanto, o acima fornece (próximo a) uma chance em dez.Você pode usar isso para produzir uma função que se comporte conforme descrito na sua pergunta, pelo menos no Bash:
Esquecer de fornecer um argumento, ou fornecer um argumento inválido, produzirá o resultado 1, portanto
chance && do_stuff
nunca o serádo_stuff
.Esta utiliza a fórmula geral para a “1 em n ” utilizando
$RANDOM
, o que é[[ $RANDOM -lt $((32767 / n + 1)) ]]
, dando um (⎣32767 / n ⎦ + 1) em 32768 acaso. Valoresn
que não são fatores de 32768 introduzem um viés por causa da divisão desigual no intervalo de valores possíveis.fonte
$((32767/parts+1))
maior que 1 ou corremos o risco de aumentar o número de partes em 1, enquanto o resultado da divisão (e, portanto, o limite) é o mesmo. (cont ..)(32767/n-32767/(n+1))>=1
resolver n que fornece um limite em ~ 181,5. De fato, o número de peças pode chegar a 194 sem problemas. Mas em 195 partes, o limite resultante é 151, o mesmo resultado que em 194 partes. Isso é incongruente e deve ser evitado. Em resumo, o limite superior para o número de partes (n) deve ser 194. Você pode fazer os testes de limite:[[ -z $1 || $1 -le 1 || $1 -ge 194 ]] && return 1
Solução não padrão:
[ $(date +%1N) == 1 ] && do_stuff
Verifique se o último dígito da hora atual em nanossegundos é 1!
fonte
[ $(date +%1N) == 1 ] && do_stuff
não ocorra em intervalos regulares, caso contrário, a aleatoriedade será estragada. Pensewhile true; do [ $(date +1%N) == 1 ] && sleep 1; done
como um contra-exemplo abstrato. No entanto, a idéia de jogar com os nanossegundos é realmente bom, eu acho que vai usá-lo, daí +1clock_getres()
), 2) O agendador não é proibido de, por exemplo, sempre iniciar uma divisão de tempo em um limite de 100 nanossegundos (o que introduziria viés mesmo que o relógio estivesse correto), 3) A maneira suportada de obter valores aleatórios é (geralmente) lendo/dev/urandom
ou inspecionando o valor de$RANDOM
.Uma alternativa ao uso
$RANDOM
é oshuf
comando:fará o trabalho. Também é útil para selecionar linhas aleatoriamente de um arquivo, por exemplo. para uma lista de reprodução de música.
fonte
Melhorando a primeira resposta e tornando muito mais óbvio o que você está tentando alcançar:
fonte
$RANDOM % 10
terá um viés, a menos que o$RANDOM
produz exatamente um múltiplo de 10 valores diferentes (o que geralmente não acontece em um computador binário)"$RANDOM" -lt $((32767 / n + 1))
.Não tenho certeza se você deseja aleatoriedade ou periodicidade ... Para periodicidade:
Você pode misturá-lo com o truque "$ RANDOM" acima para produzir algo mais caótico, por exemplo:
para eu dentro
seq 1 1000 $RANDOM
; echo $ i; doneHTH :-)
fonte