Saya ingin cara menjalankan perintah secara acak, katakan 1 dari 10 kali. Apakah ada builtin atau GNU coreutil untuk melakukan ini, idealnya kira-kira seperti:
chance 10 && do_stuff
di mana do_stuff
hanya dieksekusi 1 dari 10 kali? Saya tahu saya bisa menulis naskah, tetapi sepertinya hal yang cukup sederhana dan saya bertanya-tanya apakah ada cara yang pasti.
Jawaban:
Di
ksh
, Bash, Zsh, Yash atau BusyBoxsh
:The
RANDOM
variabel khusus dari Korn, Bash, Yash, Z dan kerang BusyBox menghasilkan nilai integer desimal pseudo-acak antara 0 dan 32.767 setiap kali itu dievaluasi, sehingga di atas memberikan (dekat) satu-in-sepuluh kesempatan.Anda dapat menggunakan ini untuk menghasilkan fungsi yang berperilaku seperti yang dijelaskan dalam pertanyaan Anda, setidaknya di Bash:
Lupa memberikan argumen, atau memberikan argumen yang tidak valid, akan menghasilkan hasil 1, jadi
chance && do_stuff
tidak akan pernahdo_stuff
.Ini menggunakan rumus umum untuk penggunaan “1 in n ”
$RANDOM
, yaitu[[ $RANDOM -lt $((32767 / n + 1)) ]]
, memberikan (⎣32767 / n ⎦ + 1) pada peluang 32768. Nilain
yang bukan merupakan faktor 32768 menimbulkan bias karena perbedaan yang tidak merata dalam rentang nilai yang mungkin.sumber
$((32767/parts+1))
lebih besar dari 1 atau kita menghadapi risiko memiliki jumlah bagian meningkat dalam 1 sedangkan hasil pembagian (dan karenanya batas) sama. (lanjutan ..)(32767/n-32767/(n+1))>=1
, penyelesaian untuk n yang memberikan batas pada ~ 181,5. Bahkan jumlah bagian bisa berjalan hingga 194 tanpa masalah. Tetapi pada 195 bagian, batas yang dihasilkan adalah 151, hasil yang sama dengan 194 bagian. Itu tidak sesuai dan harus dihindari. Singkatnya, batas atas untuk jumlah bagian (n), harus 194. Anda bisa melakukan tes batas:[[ -z $1 || $1 -le 1 || $1 -ge 194 ]] && return 1
Solusi non-standar:
[ $(date +%1N) == 1 ] && do_stuff
Periksa apakah digit terakhir dari waktu saat ini dalam nanodetik adalah 1!
sumber
[ $(date +%1N) == 1 ] && do_stuff
tidak terjadi secara berkala, jika tidak, keacakannya rusak. Pikirkanwhile true; do [ $(date +1%N) == 1 ] && sleep 1; done
sebagai contoh tandingan abstrak. Meskipun demikian, gagasan bermain dengan nanodetik sangat bagus, saya pikir saya akan menggunakannya, maka +1clock_getres()
), 2) Penjadwal tidak dilarang, misalnya, selalu memulai kutu waktu pada batas 100-nanosecond (yang akan menimbulkan bias bahkan jika jamnya benar), 3) Cara yang didukung untuk mendapatkan nilai acak adalah (biasanya) membaca dari/dev/urandom
atau memeriksa nilai$RANDOM
.Alternatif untuk menggunakan
$RANDOM
adalahshuf
perintah:akan melakukan pekerjaan itu. Juga berguna untuk memilih garis secara acak dari suatu file, mis. untuk daftar putar musik.
sumber
Memperbaiki jawaban pertama dan membuatnya lebih jelas apa yang ingin Anda capai:
sumber
$RANDOM % 10
akan memiliki bias, kecuali$RANDOM
menghasilkan kelipatan tepat dari 10 nilai yang berbeda (yang umumnya tidak terjadi di komputer biner)"$RANDOM" -lt $((32767 / n + 1))
.Saya tidak yakin apakah Anda menginginkan keacakan atau periodisitas ... Untuk periodisitas:
Anda dapat mencampurnya dengan trik "$ RANDOM" di atas untuk menghasilkan sesuatu yang lebih kacau, misalnya:
untuk saya masuk
seq 1 1000 $RANDOM
; lakukan echo $ i; dilakukanHTH :-)
sumber