Menggunakan / dev / random, / dev / urandom untuk menghasilkan data acak

12

Saya mencari cara untuk menggunakan /dev/random(atau /dev/urandom) dari baris perintah. Secara khusus, saya ingin tahu cara menggunakan aliran seperti stdinuntuk 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/randomdan /dev/urandomtidak 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:

  1. Saya menggunakan hexdumpbukan odkarena itu memberi saya cara yang lebih mudah untuk memformat output seperti yang saya inginkan;
  2. Namun yang menjengkelkan, hexdumptidak mendukung bilangan bulat 64-bit (wtf ???);
  3. Antarmuka fungsi perlu bekerja (misalnya mereka harus menerimanya -n5juga -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'
}
kjo
sumber
1
tr -cs '[:digit:]' '[\n*]' </dev/urandomseharusnya memberi Anda angka integer saja.
cuonglm
Sejauh yang saya sadari, / dev / random tidak menghasilkan angka acak per se, tetapi menambahkan suara ke fungsi matematika yang memberikan angka pseudo-acak agar mereka menjadi kurang dapat diprediksi. Anda mungkin ingin melihat randomlib.sourceforge.net
Rui F Ribeiro
Apakah Anda memerlukan keacakan kualitas kripto, atau misalnya penyemaian berdasarkan waktu yang cukup baik?
Gilles 'SANGAT berhenti menjadi jahat'
@Gilles: motivasi untuk pertanyaan saya lebih untuk mencari tahu tentang alat shell dan Unix daripada tentang keacakan; Saya hanya ingin tahu apa alat Unix dasar yang ada untuk mengubah aliran data biner ke representasi string mereka.
kjo

Jawaban:

21

Anda dapat menggunakan oduntuk mendapatkan nomor dari /dev/randomdan /dev/urandom.

Sebagai contoh,

2 byte bilangan bulat desimal yang tidak ditandatangani,

$ od -vAn -N2 -tu2 < /dev/urandom
24352

1 byte ditandatangani bilangan bulat desimal,

$ od -vAn -N1 -td1 < /dev/urandom
-78

Bilangan bulat desimal unsigned 4 byte,

$ od -vAn -N4 -tu4 < /dev/urandom
3394619386

man oduntuk informasi lebih lanjut tentang od.

EightBitTony
sumber
8

Beberapa shell (misalnya bash(1)) memiliki $RANDOM"variabel" yang memberikan angka acak.

vonbrand
sumber
1

Anda dapat melakukan sesuatu seperti:

perl -le '
  while (q(
    c char,  C unsigned char, s! short, S! unsigned short,
    i! int,  I! unsigned int, l! long,  L! unsigned long,
    f float, d double,) =~ /(\S+) (.*?),/gs) {
    $size = length(pack $1, 0);
    sysread STDIN, $data, $size;
    print "$2($size): " . unpack($1, $data);
  }' < /dev/urandom

Yang pada sistem 64 bit akan memberi Anda sesuatu seperti:

char(1): -98
unsigned char(1): 62
short(2): -12526
unsigned short(2): 399
int(4): 499066219
unsigned int(4): 2312134917
long(8): -4889591208978026255
unsigned long(8): 2080566823379835456
float(4): 55.4727554321289
double(8): 8.6395690272822e-05
Stéphane Chazelas
sumber