Saya mencari cara untuk menggunakan /dev/random
(atau /dev/urandom
) dari baris perintah. Secara khusus, saya ingin tahu cara menggunakan aliran seperti stdin
untuk menulis aliran angka acak ke stdout
(satu angka per baris).
Saya tertarik pada angka acak untuk semua jenis numerik yang didukung oleh arsitektur mesin secara asli. Misalnya untuk arsitektur 64-bit, ini akan mencakup bilangan bulat 64-bit yang ditandatangani dan tidak ditandatangani, dan angka floating point 64-bit. Sejauh rentang pergi, rentang maksimal untuk berbagai jenis numerik akan dilakukan.
Saya tahu bagaimana melakukan semua ini dengan penerjemah serba guna seperti Perl, Python, dll., Tetapi saya ingin tahu bagaimana melakukan ini dengan alat "sederhana" dari shell. (Dengan "lebih sederhana" maksud saya "lebih mungkin tersedia bahkan dalam instalasi Unix yang sangat minim".)
Pada dasarnya masalah mengurangi konversi data biner ke representasi string mereka pada baris perintah. (Misalnya, ini tidak akan berfungsi:. printf '%f\n' $(head -c8 /dev/random)
)
Saya mencari jawaban shell-agnostik. Juga, perbedaan antara /dev/random
dan /dev/urandom
tidak penting untuk pertanyaan ini. Saya berharap bahwa prosedur apa pun yang bekerja untuk satu akan bekerja untuk yang lain, bahkan ketika semantik hasil mungkin berbeda.
Saya mengadaptasi jawaban EightBitTony untuk menghasilkan fungsi toints
, dll yang ditunjukkan di bawah ini.
Contoh penggunaan:
% < /dev/urandom toprobs -n 5
0.237616281778928
0.85578479125532
0.0330049682019756
0.798812391655243
0.138499033902422
Catatan:
- Saya menggunakan
hexdump
bukanod
karena itu memberi saya cara yang lebih mudah untuk memformat output seperti yang saya inginkan; - Namun yang menjengkelkan,
hexdump
tidak mendukung bilangan bulat 64-bit (wtf ???); - Antarmuka fungsi perlu bekerja (misalnya mereka harus menerimanya
-n5
juga-n 5
), tetapi mengingat skill pemrograman shell saya yang menyedihkan, ini adalah yang terbaik yang bisa saya lakukan dengan cepat. (Komentar / peningkatan diterima, seperti biasa.)
Kejutan besar yang saya dapatkan dari latihan ini adalah menemukan betapa sulitnya memprogram pada shell hal-hal numerik yang paling dasar (misalnya membaca float heksadesimal, atau mendapatkan nilai float asli maksimum) ...
_tonums () {
local FUNCTION_NAME=$1 BYTES=$2 CODE=$3
shift 3
local USAGE="Usage: $FUNCTION_NAME [-n <INTEGER>] [FILE...]"
local -a PREFIX
case $1 in
( -n ) if (( $# > 1 ))
then
PREFIX=( head -c $(( $2 * $BYTES )) )
shift 2
else
echo $USAGE >&2
return 1
fi ;;
( -* ) echo $USAGE >&2
return 1 ;;
( * ) PREFIX=( cat ) ;;
esac
local FORMAT=$( printf '"%%%s\\n"' $CODE )
$PREFIX "$@" | hexdump -ve $FORMAT
}
toints () {
_tonums toints 4 d "$@"
}
touints () {
_tonums touints 4 u "$@"
}
tofloats () {
_tonums tofloats 8 g "$@"
}
toprobs () {
_tonums toprobs 4 u "$@" | perl -lpe '$_/=4294967295'
}
tr -cs '[:digit:]' '[\n*]' </dev/urandom
seharusnya memberi Anda angka integer saja.