Gunakan $RANDOM. Ini sering berguna dalam kombinasi dengan aritmatika shell sederhana. Misalnya, untuk menghasilkan angka acak antara 1 dan 10 (inklusif):
$ echo $((1+ RANDOM %10))3
Generator yang sebenarnya ada variables.c, fungsinya brand(). Versi yang lebih lama adalah generator linier sederhana. Versi 4.0 bashmenggunakan generator dengan kutipan ke kertas 1985, yang mungkin berarti itu adalah sumber angka pseudorandom yang layak. Saya tidak akan menggunakannya untuk simulasi (dan tentu saja tidak untuk crypto), tetapi mungkin cukup untuk tugas-tugas scripting dasar.
Jika Anda melakukan sesuatu yang memerlukan angka acak serius yang dapat Anda gunakan /dev/randomatau /dev/urandomjika tersedia:
Hati-hati di sini. Meskipun hal ini baik-baik saja dalam keadaan darurat, melakukan aritmatika pada angka acak dapat secara dramatis memengaruhi keacakan hasil Anda. dalam kasus $RANDOM % 108 dan 9 secara terukur (meskipun secara marginal) kurang mungkin dari 0-7, bahkan jika $RANDOMmerupakan sumber data acak yang kuat.
dimo414
3
@ dimo414 Saya ingin tahu "secara marginal", apakah Anda memiliki sumber di mana saya dapat mengetahui lebih banyak tentang ini?
PascalVKooten
58
Dengan memodulasi input acak Anda, Anda " merpati " hasilnya. Karena $RANDOMrentang adalah 0-32767angka 0- 7petakan ke 3277berbagai input yang mungkin, tetapi 8dan 9hanya dapat diproduksi 3276dengan cara yang berbeda (karena 32768dan 32769tidak mungkin). Ini adalah masalah kecil untuk peretasan cepat, tetapi artinya hasilnya tidak acak acak. Pustaka acak, seperti Java Random, menawarkan fungsi untuk mengembalikan angka acak seragam dalam kisaran yang diberikan dengan benar, daripada hanya memodulasi angka yang tidak dapat dibagi.
dimo414
1
@ JFSebastian sangat benar - masalah dengan modulo adalah dapat merusak keseragaman setiap Ping, bukan hanya PRNGs buruk, tapi terima kasih untuk memanggil ini.
dimo414
14
Hanya untuk konteks, pigeonholing dasar untuk% 10 berarti 8 dan 9 sekitar 0,03% lebih kecil kemungkinannya terjadi daripada 0–7. Jika skrip shell Anda memerlukan angka acak seragam yang lebih akurat daripada itu, maka tentu saja gunakan mekanisme yang lebih kompleks dan tepat.
$RANDOM adalah fungsi Bash internal (bukan konstanta) yang mengembalikan integer pseudorandom dalam rentang 0 - 32767. Fungsi ini seharusnya tidak digunakan untuk menghasilkan kunci enkripsi.
@ JinKwon 32767adalah 2^16 / 2 - 1batas atas untuk integer 16 bit yang telah ditandatangani.
Jeffrey Martinez
@ JinKwon dapatkah Anda menjelaskan mengapa Anda tidak mengatakannya 2^15 - 1? Ini setara, jadi saya hanya ingin tahu apakah ada konteks yang hilang?
Brett Holman
11
@ BrettHolman Saya pikir dia sedang mencoba untuk menunjukkan "ditandatangani" bagian dari integer 16 bit yang ditandatangani. 2 ^ 16 nilai, dibagi dua untuk postive & int negatif.
cody
Jawaban ini tidak menjawab pertanyaan.
bocor
48
Anda juga dapat menggunakan shuf (tersedia di coreutils).
Saya lebih suka opsi ini karena mudah untuk menghasilkan angka acak N dengan -n. Misalnya Hasilkan 5 angka acak antara 1 dan 100 :shuf -i 1-100 -n 5
aerijman
Sejauh yang saya mengerti angkanya tidak acak. Jika Anda menentukan, shuf -i 1-10 -n 10Anda akan mendapatkan semua angka dari 1 hingga 10 persis satu. Jika Anda menentukan, -n 15Anda masih akan mendapatkan hanya 10 angka itu sekali saja. Itu hanya mengocok, tidak menghasilkan angka acak.
radlan
Untuk mendapatkan nomor acak dengan penggantian: -r
Geoffrey Anderson
36
Coba ini dari shell Anda:
$ od -A n -t d -N 1/dev/urandom
Di sini, -t dmenentukan bahwa format output harus ditandatangani desimal; -N 1mengatakan untuk membaca satu byte dari /dev/urandom.
+1 Anda tahu, pada awalnya saya berpikir mengapa Anda ingin melakukannya seperti ini, tetapi sebenarnya saya sangat menyukainya.
zelanix
1
Terima kasih telah memberikan solusi yang mencakup penyemaian. Saya tidak dapat menemukannya di mana pun!
so.very.tired
2
+1 untuk penyemaian. Mungkin perlu disebutkan bahwa srand()seed adalah waktu CPU saat ini. Jika Anda perlu menentukan seed tertentu, sehingga RNG dapat diduplikasi, gunakan di srand(x)mana xseed tersebut. Juga, dikutip dari manual fungsi numerik GNU awk, "implementasi awk yang berbeda menggunakan generator nomor acak yang berbeda secara internal." Hasilnya adalah jika Anda tertarik untuk menghasilkan distribusi statistik, Anda harus mengharapkan sedikit variasi dari satu runtime ke yang berikutnya pada platform yang berbeda (semua berjalan awkatau gawk).
Cbhihe
18
Ada $ ACAK. Saya tidak tahu persis bagaimana cara kerjanya. Tapi itu berhasil. Untuk pengujian, Anda dapat melakukan:
$ RANDOM berada dalam kisaran 0 - 32767. Anda akan berakhir dengan lebih banyak angka yang dimulai dengan 1, 2 atau 3, daripada Anda akan 4-9. Jika Anda baik-baik saja dengan distribusi yang tidak seimbang, ini akan berfungsi dengan baik.
jbo5112
2
@ jbo5112 Anda benar, bagaimana dengan menampilkan digit terakhir? echo $ {RANDOM: 0-1} untuk satu digit, $ {RANDOM: 0-2} untuk dua digit ...?
fraff
4
Jika Anda menggunakan digit terakhir, angka itu akan lebih baik, tetapi itu termasuk 0 dan 00. Pada satu digit, 0-7 akan terjadi 0,03% lebih sering daripada 8-9. Pada 2 digit, 0-67 akan terjadi 0,3% lebih sering daripada 68-99. Jika Anda membutuhkan distribusi angka acak yang bagus, semoga Anda tidak menggunakan bash. Dengan yang asli: ${RANDOM:0:1}memiliki peluang 67,8% untuk memberi Anda 1 atau 2, ${RANDOM:0:2}hanya memiliki peluang 0,03% untuk memberi Anda satu digit angka (harus 1%), dan keduanya memiliki peluang 0,003% untuk memberi Anda 0 Masih ada kasus penggunaan di mana ini baik-baik saja (mis. Input tidak konsisten).
Buruk saya, tidak membaca halaman manual dengan benar. $RANDOMhanya berlaku dari 0 hingga 32767. Seharusnya dikatakan "Angka acak sebagian besar antara 1 dan 3, dengan beberapa sayap";)
David Newcomb
1
Apa? Itu masih akan antara 0 dan 9, meskipun 8 dan 9 akan memiliki sedikit kemungkinan lebih kecil terjadi dari 0 sampai 7, seperti yang disebutkan dalam jawaban lain.
kini
6
Jika Anda menggunakan sistem linux, Anda bisa mendapatkan nomor acak dari / dev / random atau / dev / urandom. Hati-hati / dev / random akan memblokir jika tidak ada angka acak yang cukup. Jika Anda membutuhkan kecepatan lebih dari keacakan gunakan / dev / urandom.
"File" ini akan diisi dengan angka acak yang dihasilkan oleh sistem operasi. Tergantung pada implementasi / dev / random pada sistem Anda jika Anda mendapatkan nomor acak benar atau pseudo. Angka acak yang sebenarnya dihasilkan dengan noise bentuk bantuan yang dikumpulkan dari driver perangkat seperti mouse, hard drive, jaringan.
Anda bisa mendapatkan nomor acak dari file dengan dd
Saya telah mengambil beberapa dari ide-ide ini dan membuat fungsi yang seharusnya bekerja dengan cepat jika banyak angka acak diperlukan.
panggilan oditu mahal jika Anda membutuhkan banyak nomor acak. Sebagai gantinya saya menyebutnya sekali dan menyimpan 1024 nomor acak dari / dev / urandom. Ketika randdipanggil, nomor acak terakhir dikembalikan dan diskalakan. Itu kemudian dihapus dari cache. Ketika cache kosong, 1024 angka acak lainnya dibaca.
Contoh:
rand 10; echo $RET
Mengembalikan angka acak dalam RET antara 0 dan 9 inklusif.
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: Itu tidak bekerja dengan baik untuk semua N. Ini juga membuang bit acak jika digunakan dengan N. kecil. Memperhatikan bahwa (dalam hal ini) angka acak 32 bit memiliki cukup entropi untuk 9 angka acak antara 0 dan 9 (10 * 9 = 1.000.000.000 <= 2 * 32) kita dapat mengekstraksi beberapa angka acak dari setiap 32 nilai sumber acak.
#!/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
Saya mencoba ini - butuh 10 detik cpu 100% dan kemudian dicetak 10 angka yang tidak terlihat acak sama sekali.
Carlo Wood
Aku ingat sekarang. Kode ini menghasilkan 100.000 angka acak. Ini menempatkan masing-masing dalam 'bin' untuk melihat seberapa acak itu. Ada 10 nampan. Angka-angka ini harus sama jika setiap angka acak antara 0 dan 9 memiliki kemungkinan yang sama. Jika Anda ingin mencetak setiap angka, gema $ RET setelah randBetween 10.
philcolbourn
od -An -tu4 -N40 /dev/urandomakan menghasilkan 10 bilangan bulat 32 bit yang tidak ditandatangani dan dipisahkan dengan spasi. Anda bisa menyimpannya dalam sebuah array dan menggunakannya sesudahnya. kode Anda tampaknya berlebihan.
Ali
@ Ali, OP tidak menentukan bahwa mereka ingin 32 bit atau nomor acak berukuran lain. Saya dan beberapa orang lainnya menafsirkan pertanyaan ini sebagai memberikan nomor acak dalam suatu rentang. Fungsi rand saya mencapai tujuan ini dan juga mengurangi hilangnya entropi yang, jika habis, menyebabkan program untuk diblokir. od on / dev / urandom mengembalikan hanya 2 ^ N angka acak bit dan OP kemudian perlu menyimpan beberapa nilai ke dalam array, secara berurutan mengekstraksi mereka dari array ini, dan mengisi ulang array ini. Mungkin Anda bisa mengkodekan ini sebagai jawaban dan menangani rentang angka acak lainnya?
philcolbourn
@ philcolbourn, Anda benar tentang OP tidak menentukan apa nomor acak yang dia inginkan dan itu merindukan perhatian saya. Tetapi dia hanya bertanya: "Bagaimana cara menghasilkan angka acak dalam bash?" Maksud saya adalah dia hanya meminta satu nomor acak. Meskipun kritik ini berlaku untuk komentar saya sebelumnya (menghasilkan 10 angka acak) juga.
Ali
5
Membaca dari file khusus karakter / dev / random atau / dev / urandom adalah cara yang harus dilakukan.
Perangkat ini mengembalikan angka acak ketika dibaca dan dirancang untuk membantu perangkat lunak aplikasi memilih kunci aman untuk enkripsi. Angka acak tersebut diekstraksi dari kumpulan entropi yang disumbangkan oleh berbagai peristiwa acak. {LDD3, Jonathan Corbet, Alessandro Rubini, dan Greg Kroah-Hartman]
Kedua file ini adalah antarmuka untuk pengacakan kernel, khususnya
void get_random_bytes_arch(void* buf, int nbytes)
yang menarik byte benar-benar acak dari perangkat keras jika fungsi tersebut dilakukan dengan perangkat keras (biasanya), atau menarik dari kumpulan entropi (terdiri dari pengaturan waktu antara peristiwa seperti mouse dan keyboard interupsi dan interupsi lainnya yang terdaftar pada SA_SAMPLE_RANDOM).
dd if=/dev/urandom count=4 bs=1| od -t d
Ini berfungsi, tetapi menulis keluaran yang tidak dibutuhkan dari ddke stdout. Perintah di bawah ini hanya memberikan integer yang saya butuhkan. Saya bahkan bisa mendapatkan jumlah bit acak yang ditentukan sesuai kebutuhan dengan penyesuaian bitmask yang diberikan untuk ekspansi aritmatika:
Untuk nomor acak yang aman secara kriptografis, Anda perlu membaca dari / dev / urandom atau menggunakan pustaka Crypt :: Random.
kh
3
Mungkin saya sedikit terlambat, tetapi bagaimana dengan menggunakan jotuntuk menghasilkan angka acak dalam rentang di Bash?
jot -r -p 3101
Ini menghasilkan angka acak ( -r) dengan 3 tempat desimal presisi ( -p). Dalam kasus khusus ini, Anda akan mendapatkan satu angka antara 0 dan 1 ( 1 0 1). Anda juga dapat mencetak data berurutan. Sumber nomor acak, menurut manual, adalah:
Angka acak diperoleh melalui arc4random (3) saat tidak ada benih yang ditentukan, dan melalui acak (3) saat benih diberikan.
Jawaban:
Gunakan
$RANDOM
. Ini sering berguna dalam kombinasi dengan aritmatika shell sederhana. Misalnya, untuk menghasilkan angka acak antara 1 dan 10 (inklusif):Generator yang sebenarnya ada
variables.c
, fungsinyabrand()
. Versi yang lebih lama adalah generator linier sederhana. Versi 4.0bash
menggunakan generator dengan kutipan ke kertas 1985, yang mungkin berarti itu adalah sumber angka pseudorandom yang layak. Saya tidak akan menggunakannya untuk simulasi (dan tentu saja tidak untuk crypto), tetapi mungkin cukup untuk tugas-tugas scripting dasar.Jika Anda melakukan sesuatu yang memerlukan angka acak serius yang dapat Anda gunakan
/dev/random
atau/dev/urandom
jika tersedia:sumber
$RANDOM % 10
8 dan 9 secara terukur (meskipun secara marginal) kurang mungkin dari 0-7, bahkan jika$RANDOM
merupakan sumber data acak yang kuat.$RANDOM
rentang adalah0-32767
angka0
-7
petakan ke3277
berbagai input yang mungkin, tetapi8
dan9
hanya dapat diproduksi3276
dengan cara yang berbeda (karena32768
dan32769
tidak mungkin). Ini adalah masalah kecil untuk peretasan cepat, tetapi artinya hasilnya tidak acak acak. Pustaka acak, seperti JavaRandom
, menawarkan fungsi untuk mengembalikan angka acak seragam dalam kisaran yang diberikan dengan benar, daripada hanya memodulasi angka yang tidak dapat dibagi.Silakan lihat
$RANDOM
:sumber
32767
ada arti khusus?32767
adalah2^16 / 2 - 1
batas atas untuk integer 16 bit yang telah ditandatangani.2^15 - 1
? Ini setara, jadi saya hanya ingin tahu apakah ada konteks yang hilang?Anda juga dapat menggunakan shuf (tersedia di coreutils).
sumber
shuf -i 1-10 -n 1: syntax error in expression (error token is "1-10 -n 1")
$var
bukan rentang akhir, seperti ini:var=100 && shuf -i 1-${var} -n 1
-n
. Misalnya Hasilkan 5 angka acak antara 1 dan 100 :shuf -i 1-100 -n 5
shuf -i 1-10 -n 10
Anda akan mendapatkan semua angka dari 1 hingga 10 persis satu. Jika Anda menentukan,-n 15
Anda masih akan mendapatkan hanya 10 angka itu sekali saja. Itu hanya mengocok, tidak menghasilkan angka acak.Coba ini dari shell Anda:
Di sini,
-t d
menentukan bahwa format output harus ditandatangani desimal;-N 1
mengatakan untuk membaca satu byte dari/dev/urandom
.sumber
od -A n -t d -N 1 /dev/urandom |tr -d ' '
Anda juga bisa mendapatkan nomor acak dari awk
sumber
srand()
seed adalah waktu CPU saat ini. Jika Anda perlu menentukan seed tertentu, sehingga RNG dapat diduplikasi, gunakan disrand(x)
manax
seed tersebut. Juga, dikutip dari manual fungsi numerik GNU awk, "implementasi awk yang berbeda menggunakan generator nomor acak yang berbeda secara internal." Hasilnya adalah jika Anda tertarik untuk menghasilkan distribusi statistik, Anda harus mengharapkan sedikit variasi dari satu runtime ke yang berikutnya pada platform yang berbeda (semua berjalanawk
ataugawk
).Ada $ ACAK. Saya tidak tahu persis bagaimana cara kerjanya. Tapi itu berhasil. Untuk pengujian, Anda dapat melakukan:
sumber
Saya suka trik ini:
...
sumber
${RANDOM:0:1}
memiliki peluang 67,8% untuk memberi Anda 1 atau 2,${RANDOM:0:2}
hanya memiliki peluang 0,03% untuk memberi Anda satu digit angka (harus 1%), dan keduanya memiliki peluang 0,003% untuk memberi Anda 0 Masih ada kasus penggunaan di mana ini baik-baik saja (mis. Input tidak konsisten).Angka acak antara 0 dan 9 inklusif.
sumber
$RANDOM
hanya berlaku dari 0 hingga 32767. Seharusnya dikatakan "Angka acak sebagian besar antara 1 dan 3, dengan beberapa sayap";)Jika Anda menggunakan sistem linux, Anda bisa mendapatkan nomor acak dari / dev / random atau / dev / urandom. Hati-hati / dev / random akan memblokir jika tidak ada angka acak yang cukup. Jika Anda membutuhkan kecepatan lebih dari keacakan gunakan / dev / urandom.
"File" ini akan diisi dengan angka acak yang dihasilkan oleh sistem operasi. Tergantung pada implementasi / dev / random pada sistem Anda jika Anda mendapatkan nomor acak benar atau pseudo. Angka acak yang sebenarnya dihasilkan dengan noise bentuk bantuan yang dikumpulkan dari driver perangkat seperti mouse, hard drive, jaringan.
Anda bisa mendapatkan nomor acak dari file dengan dd
sumber
Saya telah mengambil beberapa dari ide-ide ini dan membuat fungsi yang seharusnya bekerja dengan cepat jika banyak angka acak diperlukan.
panggilan
od
itu mahal jika Anda membutuhkan banyak nomor acak. Sebagai gantinya saya menyebutnya sekali dan menyimpan 1024 nomor acak dari / dev / urandom. Ketikarand
dipanggil, nomor acak terakhir dikembalikan dan diskalakan. Itu kemudian dihapus dari cache. Ketika cache kosong, 1024 angka acak lainnya dibaca.Contoh:
Mengembalikan angka acak dalam RET antara 0 dan 9 inklusif.
UPDATE: Itu tidak bekerja dengan baik untuk semua N. Ini juga membuang bit acak jika digunakan dengan N. kecil. Memperhatikan bahwa (dalam hal ini) angka acak 32 bit memiliki cukup entropi untuk 9 angka acak antara 0 dan 9 (10 * 9 = 1.000.000.000 <= 2 * 32) kita dapat mengekstraksi beberapa angka acak dari setiap 32 nilai sumber acak.
sumber
od -An -tu4 -N40 /dev/urandom
akan menghasilkan 10 bilangan bulat 32 bit yang tidak ditandatangani dan dipisahkan dengan spasi. Anda bisa menyimpannya dalam sebuah array dan menggunakannya sesudahnya. kode Anda tampaknya berlebihan.Membaca dari file khusus karakter / dev / random atau / dev / urandom adalah cara yang harus dilakukan.
Kedua file ini adalah antarmuka untuk pengacakan kernel, khususnya
yang menarik byte benar-benar acak dari perangkat keras jika fungsi tersebut dilakukan dengan perangkat keras (biasanya), atau menarik dari kumpulan entropi (terdiri dari pengaturan waktu antara peristiwa seperti mouse dan keyboard interupsi dan interupsi lainnya yang terdaftar pada SA_SAMPLE_RANDOM).
Ini berfungsi, tetapi menulis keluaran yang tidak dibutuhkan dari
dd
ke stdout. Perintah di bawah ini hanya memberikan integer yang saya butuhkan. Saya bahkan bisa mendapatkan jumlah bit acak yang ditentukan sesuai kebutuhan dengan penyesuaian bitmask yang diberikan untuk ekspansi aritmatika:sumber
Bagaimana dengan:
sumber
Mungkin saya sedikit terlambat, tetapi bagaimana dengan menggunakan
jot
untuk menghasilkan angka acak dalam rentang di Bash?Ini menghasilkan angka acak (
-r
) dengan 3 tempat desimal presisi (-p
). Dalam kasus khusus ini, Anda akan mendapatkan satu angka antara 0 dan 1 (1 0 1
). Anda juga dapat mencetak data berurutan. Sumber nomor acak, menurut manual, adalah:sumber
Berdasarkan jawaban hebat dari @Nelson, @Barun dan @Robert, berikut adalah skrip Bash yang menghasilkan angka acak.
/dev/urandom
yang jauh lebih baik daripada bawaan Bash$RANDOM
sumber
Hasilkan angka acak dalam kisaran 0 hingga n (bertanda integer 16-bit). Hasil ditetapkan dalam variabel $ RAND. Sebagai contoh:
sumber
Percabangan acak suatu program atau ya / tidak; 1/0; output benar / salah:
dari jika Anda malas mengingat 16383:
sumber