web-dev-qa-db-fra.com

Comment exécuter une commande 1 fois sur N fois dans Bash

Je veux un moyen d'exécuter une commande au hasard, disons 1 fois sur 10. Existe-t-il un code intégré ou GNU coreutil pour ce faire, idéalement quelque chose comme:

chance 10 && do_stuff

do_stuff n'est exécuté que 1 fois sur 10? Je sais que je pourrais écrire un script, mais cela semble être une chose assez simple et je me demandais s'il y avait une manière définie.

15
retnikt

Dans ksh, Bash, Zsh, Yash ou BusyBox sh:

[ "$RANDOM" -lt 3277 ] && do_stuff

La variable spéciale RANDOM des shells Korn, Bash, Yash, Z et BusyBox produit une valeur entière décimale pseudo-aléatoire entre 0 et 32767 chaque fois qu'elle est évaluée, donc ce qui précède donne (presque) un one-in -une chance.

Vous pouvez l'utiliser pour produire une fonction qui se comporte comme décrit dans votre question, au moins dans Bash:

function chance {
  [[ -z $1 || $1 -le 0 ]] && return 1
  [[ $RANDOM -lt $((32767 / $1 + 1)) ]]
}

Oublier de fournir un argument, ou fournir un argument non valide, produira un résultat de 1, donc chance && do_stuff Ne sera jamais do_stuff.

Cela utilise la formule générale pour "1 dans n" en utilisant $RANDOM, Qui est [[ $RANDOM -lt $((32767 / n + 1)) ]], donnant un ((32767/n ⎦ + 1) en 32768 chances. Les valeurs de n qui ne sont pas des facteurs de 32768 introduisent un biais en raison de la répartition inégale dans la plage de valeurs possibles.

40
Stephen Kitt

Solution non standard:

[ $(date +%1N) == 1 ] && do_stuff

Vérifiez si le dernier chiffre de l'heure actuelle en nanosecondes est 1!

25
stackzebra

Une alternative à l'utilisation de $RANDOM est la commande shuf:

[[ $(shuf -i 1-10 -n 1) == 1 ]] && do_stuff

fera le travail. Également utile pour sélectionner au hasard des lignes dans un fichier, par exemple. pour une playlist de musique.

21
seumasmac

Améliorer la première réponse et rendre beaucoup plus évident ce que vous essayez de réaliser:

[ $(( $RANDOM % 10 )) == 0 ] && echo "You win" || echo "You lose"
12
Eisenknurr

Je ne sais pas si vous voulez du hasard ou de la périodicité ... Pour la périodicité:

for i in `seq 1 10 100`; do echo $i;done
1
11
21
31
41
51
61
71
81
91

Vous pouvez le mélanger avec l'astuce "$ RANDOM" ci-dessus pour produire quelque chose de plus chaotique, par exemple:

pour i dans seq 1 1000 $RANDOM; faire écho $ i; fait

HTH :-)

1
Dr_ST