Script saya menghasilkan output yang sama saat menggunakan $ RANDOM

8

Saya mencoba untuk mencetak nkata huruf acak , di mana saya masukan ndari baris perintah itu sendiri, tetapi untuk beberapa alasan skrip saya memberi saya jawaban yang sama setiap kali ketika menggunakan nilai yang sama untuk n.

#!/bin/bash                                                                                                                                       
num=$1
egrep "^.{$num}$" /usr/share/dict/words | head -n $RANDOM| tail -n 1

Saya memanggil skrip saya seperti:

$ bash var3.sh 5
étude             # always the same output when using 5 

$ bash var3.sh 3
zoo               # always the same output when using 3

di mana var3.shnama skrip saya dan 5 adalah panjang kata yang ingin saya cetak secara acak.

Bagaimana cara saya mencetak kata yang benar-benar acak?

Karan Singh
sumber
3
$RANDOMkemungkinan besar lebih besar daripada jumlah kata n- newsletter untuk sebagian besar nilai n (95,7% dari waktu untuk n = 3 untuk saya).
Michael Homer
Apakah Anda ingin mencetak kata acak sepenuhnya, meskipun itu bukan kata atau mencetaknya secara acak dari dikt?
iZodiac
Jika tugas Anda terkait dengan keamanan (misalnya untuk membuat kata sandi), Anda harus menggunakan alat yang dibuat untuk tugas itu. Kalau tidak, dimungkinkan untuk menggunakan shufatau sort -Rseperti yang disarankan dalam jawaban. Anda juga dapat menggunakan $RANDOM, tetapi dengan cara yang lebih maju. Semua alat ini menghasilkan hasil yang dapat diprediksi (mereka tidak benar-benar acak), tetapi mereka cepat dan cukup baik untuk banyak tujuan.
sudodus
1
Mungkin mereka menggunakan metode ini (referensi
XKCD

Jawaban:

20

Tidak. Tetapi $ RANDOM mengembalikan angka besar (antara 0 dan 32767) yang, terutama untuk kata-kata dengan panjang terbatas, menunjukkan hasil yang sama, karena headbagian tersebut mungkin mengembalikan semua hasil grep (untuk 3, hanya ada 819 pertandingan di saya /usr/share/dict/words).

Solusi yang lebih baik mungkin untuk mengocok hasil:

egrep "^.{$num}$" /usr/share/dict/words | sort -R | tail -n 1

di mana -Rberarti --random-sort( sortekstensi GNU ).

Jakub Lucký
sumber
16
Mengapa tail? Itu masuk akal dalam skrip OP, tetapi karena Anda mengocok Anda juga bisa menggunakan head, dan kemudian sortharus dapat mendeteksi pipa yang rusak dan tidak repot-repot mengocok sisa garis.
Peter Taylor
@PeterTaylor mungkin tip yang bagus. Menggunakan ekor hanyalah kebiasaan saya ... Pada akhirnya, saya mungkin lebih suka shuf -n1, yang merupakan satu pipa lebih sedikit ...
Jakub Lucký
19

Metode sederhana untuk mencetak kata num- newsletter sewenang-wenang menggunakan shuf:

egrep "^.{$num}$" /usr/share/dict | shuf -n1

The shufperintah output permutasi acak dari input, dan -n1bendera mengatakan itu untuk hanya output item pertama dari hasil ini.

Rubah
sumber
3
atau grep -Ex ".{$num}". Atau awk 'length == n' n="$num"'.
Stéphane Chazelas
5

Seperti yang telah ditunjukkan orang lain, masalah utama dengan kode Anda adalah bahwa $RANDOMlebih sering daripada tidak akan menjadi nilai yang jauh lebih besar daripada jumlah kata dengan panjang tertentu.

Hanya menggunakan awk:

$ awk -v len="$num" 'length == len { word[i++]=$0 }
                     END { print word[int(i*rand())] }' /usr/share/dict/words
Bosniac

Program membaca di semua baris dari file yang diberikan dengan panjang tertentu. Ini disimpan dalam array words.

Pada akhirnya, elemen acak dari array ini dipilih dan dicetak.

Kusalananda
sumber