Hoe kan ik een willekeurig getal genereren in Bash?

Hoe genereer je een willekeurig getal binnen een bereik in Bash?


Antwoord 1, autoriteit 100%

Gebruik $RANDOM. Het is vaak handig in combinatie met eenvoudige shell-rekenkunde. Om bijvoorbeeld een willekeurig getal tussen 1 en 10 te genereren (inclusief):

$ echo $((1 + $RANDOM % 10))
3

De eigenlijke generator zit in variables.c, de functie brand(). Oudere versieswaren een eenvoudige lineaire generator. Versie 4.0 van bashgebruikt een generator met een citaat naar een paper uit 1985, wat vermoedelijk betekent dat het een behoorlijke bron van pseudo-willekeurige getallen is. Ik zou het niet gebruiken voor een simulatie (en zeker niet voor crypto), maar het is waarschijnlijk voldoende voor elementaire scripttaken.

Als je iets doet waarvoor serieuze willekeurige getallen nodig zijn, kun je /dev/randomof /dev/urandomgebruiken als ze beschikbaar zijn:

$ dd if=/dev/urandom count=4 bs=1 | od -t d

Antwoord 2, autoriteit 24%

Zie $RANDOM:

$RANDOMis een interne Bash-functie
(geen constante) die a . retourneert
pseudowillekeurig geheel getal in het bereik
0 – 32767. Het mag niet worden gebruikt om
genereer een coderingssleutel.


Antwoord 3, autoriteit 18%

Je kunt ook shuf(beschikbaar in coreutils).

shuf -i 1-100000 -n 1

Antwoord 4, autoriteit 10%

Probeer dit vanuit je shell:

$ od -A n -t d -N 1 /dev/urandom

Hier specificeert -t ddat het uitvoerformaat moet worden ondertekend decimaal; -N 1zegt één byte te lezen van /dev/urandom.


Antwoord 5, autoriteit 7%

je kunt ook een willekeurig nummer krijgen van awk

awk 'BEGIN {
   # seed
   srand()
   for (i=1;i<=1000;i++){
     print int(1 + rand() * 100)
   }
}'

Antwoord 6, autoriteit 5%

Er is $RANDOM.
Ik weet niet precies hoe het werkt. Maar het werkt.
Om te testen, kunt u het volgende doen:

echo $RANDOM

Antwoord 7, autoriteit 5%

Ik vind deze truc leuk:

echo ${RANDOM:0:1} # random number between 1 and 9
echo ${RANDOM:0:2} # random number between 1 and 99


Antwoord 8, autoriteit 3%

Willekeurig getal tussen 0 en 9, inclusief.

echo $((RANDOM%10))

Antwoord 9, autoriteit 2%

bash 5.1introduceert een nieuwe variabele, SRANDOM, die zijn willekeurige gegevens krijgt van de entropie-engine van het systeem en is dus niet lineair en kan niet opnieuw worden geplaatst om een identieke willekeurige reeks te krijgen. Deze variabele kan worden gebruikt als vervanging voor RANDOMvoor het genereren van meer willekeurigegetallen.

$ echo $((1 + SRANDOM % 10))
4

Antwoord 10

Als je een linux-systeem gebruikt, kun je een willekeurig getal halen uit /dev/ willekeurig of/dev/urandom. Wees voorzichtig /dev/random zal blokkeren als er niet genoeg willekeurige getallen beschikbaar zijn. Als je snelheid boven willekeur nodig hebt, gebruik dan /dev/urandom.

Deze “bestanden” worden gevuld met willekeurige getallen die door het besturingssysteem worden gegenereerd. Het hangt af van de implementatie van /dev/random op uw systeem of u echte of pseudo-willekeurige getallen krijgt. Echte willekeurige getallen worden gegenereerd met behulp van ruis verzameld van apparaatstuurprogramma’s zoals muis, harde schijf, netwerk.

Je kunt willekeurige getallen uit het bestand halen met dd


Antwoord 11

Ik heb een paar van deze ideeën genomen en een functie gemaakt die snel zou moeten werken als er veel willekeurige getallen nodig zijn.

bellen naar odis duur als je veel willekeurige nummers nodig hebt. In plaats daarvan noem ik het één keer en sla ik 1024 willekeurige getallen op uit /dev/urandom. Wanneer randwordt aangeroepen, wordt het laatste willekeurige getal geretourneerd en geschaald. Het wordt dan uit de cache verwijderd. Als de cache leeg is, worden nog eens 1024 willekeurige getallen gelezen.

Voorbeeld:

rand 10; echo $RET

Retourneert een willekeurig getal in RET tussen 0 en 9.

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^32
  local -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 distribution
done
for (( c=0; c<10; c++ )); do
  printf "%d %d\n" $c ${BIN[c]} 
done

UPDATE: dat werkt niet zo goed voor alle N. Het verspilt ook willekeurige bits als het wordt gebruikt met kleine N. Merk op dat (in dit geval) een 32-bits willekeurig getal voldoende entropie heeft voor 9 willekeurige getallen tussen 0 en 9 ( 10*9=1.000.000.000 <= 2*32) we kunnen meerdere willekeurige getallen extraheren uit elke 32 willekeurige bronwaarde.

#!/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]+=1
done
for c in ${BIN[*]}; do
  echo $c
done

Antwoord 12

Lezen uit /dev/random of /dev/urandom karakter speciale bestanden is de juiste keuze.

Deze apparaten retourneren echt willekeurige getallen wanneer ze worden gelezen en zijn ontworpen
om toepassingssoftware te helpen bij het kiezen van veilige sleutels voor codering. Zo een
willekeurige getallen worden geëxtraheerd uit een entropiepool die wordt bijgedragen
door verschillende willekeurige gebeurtenissen. {LDD3, Jonathan Corbet, Alessandro
Rubini en Greg Kroah-Hartman]

Deze twee bestanden zijn in het bijzonder een interface voor randomisatie van de kernel

void get_random_bytes_arch(void* buf, int nbytes)

die echt willekeurige bytes uit hardware haalt als een dergelijke functie door hardware is geïmplementeerd (meestal), of uit een entropiepool (bestaande uit timings tussen gebeurtenissen zoals muis- en toetsenbordonderbrekingen en andere onderbrekingen die zijn geregistreerd bij SA_SAMPLE_RANDOM).

dd if=/dev/urandom count=4 bs=1 | od -t d

Dit werkt, maar schrijft onnodige uitvoer van ddnaar stdout. De onderstaande opdracht geeft alleen het gehele getal dat ik nodig heb. Ik kan zelfs een gespecificeerd aantal willekeurige bits krijgen als ik nodig heb door het bitmasker aan te passen dat wordt gegeven aan rekenkundige uitbreiding:

[email protected]:~/$ x=$(head -c 1 /dev/urandom > tmp && hexdump 
                         -d tmp | head -n 1 | cut -c13-15) && echo $(( 10#$x & 127 ))

Antwoord 13

Genereer een willekeurig getal in het bereik van 0 tot n (ondertekend 16-bits geheel getal). Resultaat ingesteld in $RAND variabele. Bijvoorbeeld:

#!/bin/bash
random()
{
    local range=${1:-1}
    RAND=`od -t uI -N 4 /dev/urandom | awk '{print $2}'`
    let "RAND=$RAND%($range+1)"
}
n=10
while [ $(( n -=1 )) -ge "0" ]; do
    random 500
    echo "$RAND"
done

Antwoord 14

Hoe zit het met:

perl -e 'print int rand 10, "\n"; '

Antwoord 15

Misschien ben ik een beetje te laat, maar hoe zit het met het gebruik van jotom een willekeurig getal binnen een bereik in Bash te genereren?

jot -r -p 3 1 0 1

Dit genereert een willekeurig (-r) getal met een precisie van 3 decimalen (-p). In dit specifieke geval krijg je één getal tussen 0 en 1 (1 0 1). U kunt ook opeenvolgende gegevens afdrukken. De bron van het willekeurige getal, volgens de handleiding, is:

Willekeurige getallen worden verkregen via arc4random(3) als er geen seed is opgegeven, en via
random(3) wanneer een seed wordt gegeven.


Antwoord 16

Gebaseerd op de geweldige antwoorden van @Nelson, @Barun en @Robert, is hier een Bash-script dat willekeurige getallen genereert.

  • Kan het gewenste aantal cijfers genereren.
  • elk cijfer wordt afzonderlijk gegenereerd door /dev/urandom, wat veel beteris dan de ingebouwde $RANDOM
  • van Bash

#!/usr/bin/env bash
digits=10
rand=$(od -A n -t d -N 2 /dev/urandom |tr -d ' ')
num=$((rand % 10))
while [ ${#num} -lt $digits ]; do
  rand=$(od -A n -t d -N 1 /dev/urandom |tr -d ' ')
  num="${num}$((rand % 10))"
done
echo $num

Antwoord 17

Ik heb hier verschillende artikelen over geschreven.

$ RANDOM=$(date +%s%N | cut -b10-19)
$ echo $(( $RANDOM % 113 + 13 ))

Het bovenstaande geeft een getal tussen 13 en 113, met een redelijke willekeurige entropie.


Antwoord 18

Willekeurige vertakking van een programma of ja/nee; 1/0; waar/onwaar uitvoer:

if [ $RANDOM -gt 16383  ]; then              # 16383 = 32767/2 
    echo var=true/1/yes/go_hither
else 
    echo var=false/0/no/go_thither
fi

van als je lui bent om 16383 te onthouden:

if (( RANDOM % 2 )); then 
    echo "yes"
else 
    echo "no"
fi

Antwoord 19

Genereer een willekeurig 3-cijferig nummer

Dit is geweldig voor het maken van voorbeeldgegevens. Voorbeeld: plaats alle testgegevens in een map met de naam “test-create-volume-123”, en zap de hele map nadat uw test is voltooid. Door exact drie cijfers te genereren, heeft u geen rare sorteerproblemen.

printf '%02d\n' $((1 + RANDOM % 100))

Dit wordt kleiner, b.v. tot één cijfer:

printf '%01d\n' $((1 + RANDOM % 10))

Het schaalt op, maar slechts tot vier cijfers. Zie hierboven waarom 🙂


Antwoord 20

Wilde /dev/urandom gebruiken zonder dden od

function roll() { local modulus=${1:-6}; echo $(( 1 + 0x$(env LC_CTYPE=C tr -dc '0-9a-fA-F' < /dev/urandom | head -c5 ) % $modulus )); }

Testen

$ roll
5
$ roll 12
12

Hoe willekeurig is het?

$ (echo "count roll percentage"; i=0; while [ $i -lt 10000 ]; do roll; i=$((i+1)); done | sort | uniq -c | awk '{print $0,($1/10000*100)"%"}') | column -t
count  roll  percentage
1625   1     16.25%
1665   2     16.65%
1646   3     16.46%
1720   4     17.2%
1694   5     16.94%
1650   6     16.5%

Antwoord 21

Een bash-functie die perl gebruikt om een willekeurig aantal van n cijfers te genereren. Geef het aantal cijfers op of een sjabloon van n 0s.

rand() {
  perl -E '$ARGV[0]||=""; $ARGV[0]=int($ARGV[0])||length($ARGV[0]); say join "", int(rand(9)+1)*($ARGV[0]?1:0), map { int(rand(10)) } (0..($ARGV[0]||0)-2)' $1
}

Gebruik:

$ rand 3
381
$ rand 000
728

Demonstratie van het aanroepen van rand n, voor n tussen 0 en 15:

$ for n in {0..15}; do printf "%02d: %s\n" $n $(rand $n); done
00: 0
01: 3
02: 98
03: 139
04: 1712
05: 49296
06: 426697
07: 2431421
08: 82727795
09: 445682186
10: 6368501779
11: 51029574113
12: 602518591108
13: 5839716875073
14: 87572173490132
15: 546889624135868

Demonstratie van het aanroepen van rand n, voor n een sjabloon van nullen tussen lengte 0 en 15

$ for n in {0..15}; do printf "%15s :%02d: %s\n" $(printf "%0${n}d" 0) $n $(rand $(printf "%0${n}d" 0)); done
              0 :00: 0
              0 :01: 0
             00 :02: 70
            000 :03: 201
           0000 :04: 9751
          00000 :05: 62237
         000000 :06: 262860
        0000000 :07: 1365194
       00000000 :08: 83953419
      000000000 :09: 838521776
     0000000000 :10: 2355011586
    00000000000 :11: 95040136057
   000000000000 :12: 511889225898
  0000000000000 :13: 7441263049018
 00000000000000 :14: 11895209107156
000000000000000 :15: 863219624761093

Antwoord 22

Je kunt een seed gebruiken:

RANDOM=$(date +%s%N | cut -b10-19)
echo $(( $RANDOM % 100 + 1 ))

Other episodes