如何在Bash中生成随机数?

时间:2009-07-28 15:23:16

标签: bash shell random

如何在Bash中生成一个范围内的随机数?

22 个答案:

答案 0 :(得分:203)

使用$RANDOM。它通常与简单的shell算法结合使用。例如,要生成1到10之间的随机数:

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

实际的生成器位于variables.c,函数brand()Older versions是一个简单的线性生成器。 bash版本4.0使用generator with a citation到1985年的论文,这可能意味着它是伪随机数的合适来源。我不会将它用于模拟(当然也不用于加密),但它可能足以用于基本的脚本编写任务。

如果你正在做一些需要严重随机数字的事情,你可以使用/dev/random/dev/urandom,如果它们可用:

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

答案 1 :(得分:60)

请参阅$RANDOM

  

$RANDOM是一个内部Bash函数   (不是常数)返回一个   范围内的伪随机整数   0 - 32767.不应该习惯   生成加密密钥。

答案 2 :(得分:31)

从你的shell中试试这个:

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

这里,-t d指定输出格式应为十进制符号; -N 1说从/dev/urandom读取一个字节。

答案 3 :(得分:22)

您也可以使用 shuf (在coreutils中提供)。

shuf -i 1-100000 -n 1

答案 4 :(得分:18)

有$ RANDOM。 我不确切知道它是如何工作的。但它的确有效。 对于测试,您可以这样做:

echo $RANDOM

答案 5 :(得分:17)

你也可以从awk获得随机数

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

答案 6 :(得分:10)

0到9之间的随机数。

echo $((RANDOM%10))

答案 7 :(得分:6)

我喜欢这个技巧:

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

...

答案 8 :(得分:5)

如果您使用的是Linux系统,则可以从/dev/random or / dev / urandom中获取一个随机数。如果没有足够的随机数,请小心/ dev / random将阻止。如果你需要速度超过随机性使用/ dev / urandom。

这些“文件”将填充操作系统生成的随机数。如果你得到真或伪随机数,它取决于你的系统上/ dev / random的实现。使用从鼠标,硬盘驱动器,网络等设备驱动程序收集的噪音帮助生成真随机数。

您可以使用dd

从文件中获取随机数

答案 9 :(得分:4)

我已经采取了一些这样的想法,并且如果需要大量的随机数,那么它应该能够快速执行。

如果你需要大量的随机数,那么调用od是很昂贵的。相反,我将其称为一次并从/ dev / urandom存储1024个随机数。调用rand时,将返回最后一个随机数并进行缩放。然后将其从缓存中删除。当缓存为空时,将读取另外1024个随机数。

示例:

rand 10; echo $RET

在RET中返回0到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

更新:对于所有N来说效果都不好。如果使用小N,它也会浪费随机位。注意到(在这种情况下)32位随机数对于0到9之间的9个随机数具有足够的熵( 10 * 9 = 1,000,000,000&lt; = 2 * 32)我们可以从每个32个随机源值中提取多个随机数。

#!/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

答案 10 :(得分:4)

从/ dev / random或/ dev / urandom字符特殊文件中读取是可行的方法。

  

这些设备在读取和设计时会返回真正的随机数   帮助应用软件选择安全密钥进行加密。这样   随机数是从贡献的熵池中提取的   通过各种随机事件。 {LDD3,Jonathan Corbet,亚历山德罗   鲁比尼和Greg Kroah-Hartman]

这两个文件是内核随机化的接口,特别是

void get_random_bytes_arch(void* buf, int nbytes)

从硬件中抽取真正的随机字节,如果这些函数是通过硬件实现的(通常是),或者它是从熵池中抽取的(包括鼠标和键盘中断之类的事件之间的时序以及用SA_SAMPLE_RANDOM注册的其他中断)。 / p>

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

这样可行,但会将dd中不需要的输出写入stdout。下面的命令只给出了我需要的整数。我可以通过调整给予算术扩展的位掩码来获得指定数量的随机位:

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

答案 11 :(得分:2)

生成3位随机数字

这对于创建样本数据非常有用。示例:将所有测试数据放在一个名为“ test-create-volume-123”的目录中,然后在完成测试后,覆盖整个目录。通过生成正好三个数字,您就没有weird sorting issues

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

例如,按比例缩小到一位:

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

它可以扩展,但是只能扩展到四位数。参见上面的原因:)

答案 12 :(得分:2)

也许我为时已晚,但是使用jot生成Bash范围内的随机数呢?

jot -r -p 3 1 0 1

这将生成一个随机(-r),其精度为3个小数位(-p)。在这种情况下,您会得到一个介于0和1之间的数字(1 0 1)。您也可以打印顺序数据。根据手册,随机数的来源是:

  

在没有指定种子的情况下,通过arc4random(3)获得随机数,并通过        给出种子时为random(3)。

答案 13 :(得分:2)

基于@ Nelson,@ Barun和@Robert的出色答案,这是一个生成随机数的Bash脚本。

  • 可以生成您想要的位数。
  • 每个数字由/dev/urandom分别生成,比Bash内置的$RANDOM
#!/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

答案 14 :(得分:2)

程序的随机分支或是/否; 1/0;正确/错误输出:

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

如果您不愿记住16383:

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

答案 15 :(得分:1)

生成0到n范围内的随机数(带符号的16位整数)。结果在$ RAND变量中设置。例如:

#!/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

答案 16 :(得分:1)

bash 5.1引入了一个新变量SRANDOM,该变量从系统的熵引擎获取其随机数据,因此它不是线性的,因此无法重新植入以获得相同的随机序列。此变量可以代替RANDOM来生成更多随机数字。

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

答案 17 :(得分:1)

怎么样:

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

答案 18 :(得分:0)

想在没有 dd od

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

测试

$ roll
5
$ roll 12
12

随机性如何?

$ (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%

答案 19 :(得分:0)

一个bash函数,它使用perl生成n个数字的随机数。指定位数或n 0的模板。

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
}

用法:

$ rand 3
381
$ rand 000
728

调用rand n的演示,其中n在0到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

演示调用rand n,对于n长度在0到15之间的0s模板

$ 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

答案 20 :(得分:0)

我为此写了几篇文章。

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

上面给出的数字在13到113之间,具有合理的随机熵。

答案 21 :(得分:0)

您可以使用种子:

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