Shell進(jìn)階腳本-生成隨機(jī)數(shù)( $RANDOM )

$RANDOM 是 Bash 中用來(lái)生成 0 至 32767 之間隨機(jī)整數(shù)的一個(gè)內(nèi)置 函數(shù)(而非常量)
不應(yīng)被用于生成密鑰
樣例-1. 生成隨機(jī)數(shù)

#!/bin/bash

# $RANDOM 每一次調(diào)用都會(huì)返回一個(gè)隨機(jī)的不同的整數(shù)。
# 隨機(jī)數(shù)的標(biāo)稱范圍為 0 - 32767(16位有符號(hào)整型)产捞。

MAXCOUNT=10
count=1

echo
echo "$MAXCOUNT random numbers:"
echo "-----------------"
while [ "$count" -le $MAXCOUNT ]      # 生成 10 ($MAXCOUNT) 個(gè)隨機(jī)整數(shù)翰铡。
do
  number=$RANDOM
  echo $number
  let "count += 1"  # 增加計(jì)數(shù)掀泳。
done
echo "-----------------"

# 如果你需要一個(gè)小于指定上界的隨機(jī)數(shù)孩饼,可以使用 'modulo' 操作符晶疼。
# 該操作符可以返回除法后的余數(shù)袜蚕。

RANGE=500

echo

number=$RANDOM
let "number %= $RANGE"
#           ^^
echo "Random number less than $RANGE --- $number"

echo



#  如果你需要生成的隨機(jī)數(shù)大于一個(gè)指定的下界叽奥,
#+ 可以增加一步判斷俱两,判別并丟棄所有小于下界的數(shù)饱狂。

FLOOR=200

number=0   # 初始化
while [ "$number" -le $FLOOR ]
do
  number=$RANDOM
done
echo "Random number greater than $FLOOR --- $number"
echo

   # 現(xiàn)在來(lái)看一種可以代替上面循環(huán)的更簡(jiǎn)單的方式,也就是
   #       let "number = $RANDOM + $FLOOR"
   # 該方式可以不使用 while 循環(huán)宪彩,效率更高休讳。
   # 但是,該方法可能會(huì)產(chǎn)生一些問(wèn)題尿孔,是什么呢俊柔?



# 通過(guò)結(jié)合上面的兩種方法筹麸,可以獲得一個(gè)特定范圍內(nèi)的隨機(jī)數(shù)。
number=0   # 初始化
while [ "$number" -le $FLOOR ]
do
  number=$RANDOM
  let "number %= $RANGE"  # 將 $number 縮小至 $RANGE 的范圍內(nèi)雏婶。
done
echo "Random number between $FLOOR and $RANGE --- $number"
echo



# 生成二元選擇值物赶,即真(true)或假(false)。
BINARY=2
T=1
number=$RANDOM

let "number %= $BINARY"
#  如果使用    let "number >>= 14"    可以獲得更優(yōu)的隨機(jī)分布
#+ (除了最低位留晚,其余二進(jìn)制位都右移)酵紫。
if [ "$number" -eq $T ]
then
  echo "TRUE"
else
  echo "FALSE"
fi

echo


# 扔一個(gè)骰子。
SPOTS=6   # 模 6 的余數(shù)范圍為 0 - 5错维。
          # 然后加 1 就可以得到期望的范圍 1 - 6奖地。
          # 感謝 Paulo Marcel Coelho Aragao 簡(jiǎn)化了代碼。
die1=0
die2=0
# 如果設(shè)置 SPOTS=7 就可以不用加 1 得到值赋焕。這是不是一種更好的方法参歹,為什么?

# 為了保證公平隆判,獨(dú)立的投每一個(gè)骰子犬庇。

    let "die1 = $RANDOM % $SPOTS + 1" # 投第一個(gè)骰子。
    let "die2 = $RANDOM % $SPOTS + 1" # 投第二個(gè)骰子侨嘀。
    #  哪一種運(yùn)算符有更高的優(yōu)先級(jí)臭挽,
    #+ 取余(%)還是加法(+)?


let "throw = $die1 + $die2"
echo "Throw of the dice = $throw"
echo


exit 0

樣例-2. 從牌組中隨機(jī)選牌

#!/bin/bash
# pick-card.sh

# 該樣例演示了如何從數(shù)組中隨機(jī)選擇元素飒炎。


# 隨機(jī)選擇任意一張牌埋哟。

Suites="Clubs
Diamonds
Hearts
Spades"

Denominations="2
3
4
5
6
7
8
9
10
Jack
Queen
King
Ace"

# 注意一個(gè)變量占了多行。


suite=($Suites)                # 讀入數(shù)組變量郎汪。
denomination=($Denominations)

num_suites=${#suite[*]}        # 數(shù)組中的元素?cái)?shù)量赤赊。
num_denominations=${#denomination[*]}

echo -n "${denomination[$((RANDOM%num_denominations))]} of "
echo ${suite[$((RANDOM%num_suites))]}


# $bozo sh pick-cards.sh
# Jack of Clubs

exit 0

樣咧-3. 模擬布朗運(yùn)動(dòng)

#!/bin/bash
# brownian.sh

#  ----------------------------------------------------------------
#  該腳本模擬了布朗運(yùn)動(dòng)。
#+ 布朗運(yùn)動(dòng)是指微小粒子受到流體粒子隨機(jī)碰撞煞赢,
#+ 而在流體中做的無(wú)規(guī)則隨機(jī)運(yùn)動(dòng)抛计。
#+ 也就是俗稱的“醉漢走路”。

#  布朗運(yùn)動(dòng)也可以被視作是一個(gè)簡(jiǎn)化的高爾頓板照筑。
#+ 高爾頓板是一個(gè)有著交錯(cuò)排列的釘子的傾斜板子吹截,
#+ 每次可以從中向下滾動(dòng)一堆石子。
#+ 在板子底端是一排槽位凝危,
#+ 石子最后會(huì)落在槽位中波俄。
#  把它想象成一個(gè)簡(jiǎn)單的彈珠游戲就可以了。
#  當(dāng)運(yùn)行這個(gè)腳本之后蛾默,
#+ 你就會(huì)發(fā)現(xiàn)大部分的石子都聚集在中間的槽位里懦铺。
#+ 這與預(yù)期的二項(xiàng)分布相符。
#  作為模擬高爾頓板的程序支鸡,
#+ 腳本忽略了許多參數(shù)冬念,
#+ 例如板子的傾斜角度趁窃、石子滾動(dòng)的摩擦系數(shù)、
#+ 沖擊角度以及釘子的彈性系數(shù)等等急前。
#  忽略的這些參數(shù)能夠在多大程度上影響模擬的精度醒陆?
#  -------------------------------------------------------------

PASSES=500            #  粒子作用數(shù) / 石子數(shù)。
ROWS=10               #  碰撞數(shù) / 每一排釘子的數(shù)量裆针。
RANGE=3               #  $RANDOM 的輸出范圍為 0 - 2刨摩。
POS=0                 #  滾落左側(cè)或是右側(cè)。
RANDOM=$$             #  將腳本的進(jìn)程 ID 作為
                      #+ 生成隨機(jī)數(shù)的種子据块。

declare -a Slots      # 用于儲(chǔ)存落入每一個(gè)槽位的石子數(shù)量码邻。
NUMSLOTS=21           # 底部槽位的數(shù)量。


Initialize_Slots () { # 初始化數(shù)組另假。
for i in $( seq $NUMSLOTS )
do
  Slots[$i]=0
done

echo                  # 在正式模擬開(kāi)始之前先輸出空行。
  }


Show_Slots () {
echo; echo
echo -n " "
for i in $( seq $NUMSLOTS )   # 更精致地輸出數(shù)組中的所有元素怕犁。
do
  printf "%3d" ${Slots[$i]}   # 每個(gè)結(jié)果都占三個(gè)字符的寬度边篮。
done

echo # 槽位:
echo " |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|"
echo "                                ||"
echo #  需要注意的是,如果任意一個(gè)槽位中石子的數(shù)量超過(guò) 99奏甫,
     #+ 將會(huì)打亂整個(gè)程序的顯示效果戈轿。
     #  如果只運(yùn)行 500 次通常可以避免這個(gè)問(wèn)題阵子。
  }


Move () {              # 將一個(gè)單位左移思杯、右移或保持原地不動(dòng)。
  Move=$RANDOM         # $RANDOM 到底有多隨機(jī)挠进?讓我們看看...
  let "Move %= RANGE"  # 標(biāo)準(zhǔn)化至范圍 0 - 2色乾。
  case "$Move" in
    0 ) ;;                   # 什么也不做,也就是原地不動(dòng)领突。
    1 ) ((POS--));;          # 左移暖璧。
    2 ) ((POS++));;          # 右移。
    * ) echo -n "Error ";;   # 出現(xiàn)異常>(應(yīng)該永遠(yuǎn)不會(huì)發(fā)生)
  esac
  }


Play () {                    # 模擬單次運(yùn)行(內(nèi)部循環(huán))澎办。
i=0
while [ "$i" -lt "$ROWS" ]   # 每一排釘子經(jīng)過(guò)且僅經(jīng)過(guò)一次石子。
do
  Move
  ((i++));
done

SHIFT=11                     # 為什么是 11 而不是 10金砍?
let "POS += $SHIFT"          # 將原點(diǎn)移到中間局蚀。
(( Slots[$POS]++ ))          # 調(diào)試:echo $POS

# echo -n "$POS "

  }


Run () {                     # 外部循環(huán)。
p=0
while [ "$p" -lt "$PASSES ]
do
  Play
  (( p++ ))
  POS=0                      # 重置為 0恕稠。為什么要這么做琅绅?
done
  }


# --------------
# main ()
Initialize_Slots
Run
Show_Slots
# --------------

exit $?

#  練習(xí):
#  ---------
#  1) 將結(jié)果顯示為一張直方圖,
#+    或者是一張散點(diǎn)圖谱俭。
#  2) 修改腳本奉件,使用 /dev/urandom 提到 $RANDOM宵蛀。
#     這會(huì)使腳本更加的隨機(jī)化么?
#  3) 當(dāng)每一個(gè)石子落下的時(shí)候县貌,
#+    嘗試添加一些動(dòng)畫(huà)效果术陶。

Jipe 提供了一些生成指定范圍內(nèi)隨機(jī)數(shù)的方法

#  生成范圍為 6 到 30 的隨機(jī)數(shù)。
   rnumber=$((RANDOM%25+6))

#  生成范圍為 6 到 30 的隨機(jī)數(shù)煤痕,
#+ 并且該隨機(jī)數(shù)能被 3 整除梧宫。
   rnumber=$(((RANDOM%30/3+1)*3))

#  需要注意這種方法并不是在所有情況下都能起效。
#  會(huì)在 $RANDOM%30 為 0 時(shí)失效摆碉。

#  Frank Wang 建議可以換用下面的方法:
   rnumber=$(( RANDOM%27/3*3+6 ))

Bill Gradwohl 提出了一種改良后的僅適用于正數(shù)的公式

rnumber=$(((RANDOM%(max-min+divisibleBy))/divisibleBy*divisibleBy+min))

Bill 在這還給出了一個(gè)生成指定范圍內(nèi)隨機(jī)數(shù)的通用函數(shù)

樣例-4. 指定范圍隨機(jī)數(shù)

#!/bin/bash
# random-between.sh
# 生成指定范圍內(nèi)的隨機(jī)數(shù)塘匣。
# Anthony Le Clezio 修正了 187 行和 189 行。



randomBetween() {
   #  生成一個(gè)范圍在 $min 和 $max 之間巷帝,
   #+ 并且能被 $divisibleBy 整除的
   #+ 隨機(jī)正數(shù)或負(fù)數(shù)忌卤。
   #  返回的隨機(jī)數(shù)遵循合理的隨機(jī)分布。

   #  Bill Gradwohl - Oct 1, 2003

   syntax() {
   # 嵌套函數(shù)楞泼。
      echo
      echo    "Syntax: randomBetween [min] [max] [multiple]"
      echo
      echo -n "Expects up to 3 passed parameters, "
      echo    "but all are completely optional."
      echo    "min is the minimum value"
      echo    "max is the maximum value"
      echo -n "multiple specifies that the answer must be "
      echo     "a multiple of this value."
      echo    "    i.e. answer must be evenly divisible by this number."
      echo
      echo    "If any value is missing, defaults area supplied as: 0 32767 1"
      echo -n "Successful completion returns 0, "
      echo      "unsuccessful completion returns"
      echo    "function syntax and 1."
      echo -n "The answer is returned in the global variable "
      echo    "randomBetweenAnswer"
      echo -n "Negative values for any passed parameter are "
      echo    "handled correctly."
   }

   local min=${1:-0}
   local max=${2:-32767}
   local divisibleBy=${3:-1}
   # 考慮到?jīng)]有給函數(shù)傳參的情況驰徊,給變量設(shè)置默認(rèn)值。

   local x
   local spread

   # 確保 divisibleBy 的值為正數(shù)堕阔。
   [ ${divisibleBy} -lt 0 ] && divisibleBy=$((0-divisibleBy))

   # 合規(guī)校驗(yàn)棍厂。
   if [ $# -gt 3 -o ${divisibleBy} -eq 0 -o  ${min} -eq ${max} ]; then
      syntax
      return 1
   fi

   # 檢查 min 和 max 的值是否顛倒。
   if [ ${min} -gt ${max} ]; then
      # 交換它們超陆。
      x=${min}
      min=${max}
      max=${x}
   fi

   #  如果 min 值本身不能被 $divisibleBy 整除牺弹,
   #+ 則將其修正到范圍內(nèi)。
   if [ $((min/divisibleBy*divisibleBy)) -ne ${min} ]; then
      if [ ${min} -lt 0 ]; then
         min=$((min/divisibleBy*divisibleBy))
      else
         min=$((((min/divisibleBy)+1)*divisibleBy))
      fi
   fi

   #  如果 max 值本身不能被 $divisibleBy 整除时呀,
   #+ 則將其修正到范圍內(nèi)张漂。
   if [ $((max/divisibleBy*divisibleBy)) -ne ${max} ]; then
      if [ ${max} -lt 0 ]; then
         max=$((((max/divisibleBy)-1)*divisibleBy))
      else
         max=$((max/divisibleBy*divisibleBy))
      fi
   fi

   #  ---------------------------------------------------------------------
   #  接下來(lái)開(kāi)始真正的內(nèi)容。

   #  需要注意的是退唠,為了得到端點(diǎn)間合理的隨機(jī)分布鹃锈,
   #+ 隨機(jī)數(shù)的取值范圍應(yīng)是 0 至 abs(max-min)+divisibleBy,
   #+ 而不是簡(jiǎn)單的 abs(max-min)+1瞧预。

   #  少量的增長(zhǎng)將會(huì)帶來(lái)端點(diǎn)間
   #+ 合理的隨機(jī)分布屎债。

   #  將公式修改為使用 abs(max-min)+1 仍然可以得到正確的答案,
   #+ 但是獲得的這些隨機(jī)數(shù)的隨機(jī)性是有缺陷的垢油,
   #+ 因?yàn)檫@種情況下返回的端點(diǎn)值 ($min 和 $max) 的次數(shù)遠(yuǎn)少于
   #+ 使用正確公式時(shí)所返回的次數(shù)盆驹。
   #  ---------------------------------------------------------------------

   spread=$((max-min))
   #  Omair Eshkenazi 指出在這里沒(méi)有必要進(jìn)行校驗(yàn),
   #+ 因?yàn)?max 和 min 的值已經(jīng)被交換了滩愁。
   [ ${spread} -lt 0 ] && spread=$((0-spread))
   let spread+=divisibleBy
   randomBetweenAnswer=$(((RANDOM%spread)/divisibleBy*divisibleBy+min))

   return 0

   #  但是 Paulo Marcel Coelho Aragao 指出
   #+ 當(dāng) $max 和 $min 不能被 $divisibleBy 整除時(shí)躯喇,
   #+ 該公式就會(huì)失效。
   #
   #  他建議替換為下面的公式:
   #    rnumber = $(((RANDOM%(max-min+1)+min)/divisibleBy*divisibleBy))

}

# 接下來(lái)測(cè)試函數(shù)。
min=-14
max=20
divisibleBy=3


#  循環(huán)執(zhí)行足夠多次數(shù)的函數(shù)廉丽,生成包含這些隨機(jī)數(shù)的數(shù)組倦微,
#+ 然后校驗(yàn)數(shù)組中是否包含了端點(diǎn)范圍內(nèi)的每一個(gè)數(shù)字。

declare -a answer
minimum=${min}
maximum=${max}
   if [ $((minimum/divisibleBy*divisibleBy)) -ne ${minimum} ]; then
      if [ ${minimum} -lt 0 ]; then
         minimum=$((minimum/divisibleBy*divisibleBy))
      else
         minimum=$((((minimum/divisibleBy)+1)*divisibleBy))
      fi
   fi


   #  如果 max 值本身不能被 $divisibleBy 整除正压,
   #+ 則將其修正到范圍內(nèi)欣福。

   if [ $((maximum/divisibleBy*divisibleBy)) -ne ${maximum} ]; then
      if [ ${maximum} -lt 0 ]; then
         maximum=$((((maximum/divisibleBy)-1)*divisibleBy))
      else
         maximum=$((maximum/divisibleBy*divisibleBy))
      fi
   fi


#  需要保證數(shù)組的下標(biāo)只能為正數(shù),
#+ 因此這里需要通過(guò)位移來(lái)保證
#+ 結(jié)果為正焦履。

disp=$((0-minimum))
for ((i=${minimum}; i<=${maximum}; i+=divisibleBy)); do
   answer[i+disp]=0
done


# 現(xiàn)在開(kāi)始循環(huán)執(zhí)行函數(shù)以獲得大量的隨機(jī)數(shù)拓劝。
loopIt=1000   #  腳本的作者建議使用 100000,
              #+ 但是這會(huì)花費(fèi)大量的時(shí)間嘉裤。

for ((i=0; i<${loopIt}; i++)); do

   #  注意郑临,我們?cè)谶@里顛倒了 min 和 max 的值,
   #+ 為的是校驗(yàn)函數(shù)在這種情況下是否能正常執(zhí)行屑宠。

   randomBetween ${max} ${min} ${divisibleBy}

   # 如果獲得了非預(yù)期的答案厢洞,則報(bào)錯(cuò)。
   [ ${randomBetweenAnswer} -lt ${min} -o ${randomBetweenAnswer} -gt ${max} ] \
   && echo MIN or MAX error - ${randomBetweenAnswer}!
   [ $((randomBetweenAnswer%${divisibleBy})) -ne 0 ] \
   && echo DIVISIBLE BY error - ${randomBetweenAnswer}!

   # 保存統(tǒng)計(jì)結(jié)果典奉。
   answer[randomBetweenAnswer+disp]=$((answer[randomBetweenAnswer+disp]+1))
done



# 校驗(yàn)最終結(jié)果犀变。

for ((i=${minimum}; i<=${maximum}; i+=divisibleBy)); do
   [ ${answer[i+disp]} -eq 0 ] \
   && echo "We never got an answer of $i." \
   || echo "${i} occurred ${answer[i+disp]} times."
done

exit 0

那么 $RANDOM 到底有多隨機(jī)?最好的測(cè)試方法就是寫(xiě)一個(gè)腳本跟蹤由 $RANDOM 生成的隨機(jī)數(shù)的分布
接下來(lái)讓我們多投幾次由 $RANDOM 做的骰子

樣例-5. 用 RANDOM 投骰子

#!/bin/bash
# RANDOM 有多隨機(jī)秋柄?

RANDOM=$$       # 用腳本的進(jìn)程 ID 重置隨機(jī)數(shù)生成器種子。

PIPS=6          # 骰子有 6 個(gè)點(diǎn)蠢正。
MAXTHORWS=600   # 如果你沒(méi)有更好消磨時(shí)間的辦法骇笔,就增加這個(gè)值。
                # 投骰子的次數(shù)嚣崭。

ones=0          #  必須初始化計(jì)數(shù)器的值為 0笨触,
twos=0          #+ 因?yàn)槲闯跏蓟淖兞康闹禐?null 而非 0。
threes=0
fours=0
fives=0
sixes=0

print_result ()
{
echo
echo "ones =   $ones"
echo "twos =   $twos"
echo "threes = $threes"
echo "fours =  $fours"
echo "fives =  $fives"
echo "sixes =  $sixes"
echo
}

update_count()
{
case "$1" in
  0) ((ones++));;   # 因?yàn)轺蛔記](méi)有 0 點(diǎn)雹舀,所以這個(gè)其實(shí)對(duì)應(yīng)的是 1 點(diǎn)芦劣。
  1) ((twos++));;   # 這個(gè)對(duì)應(yīng) 2 點(diǎn)。
  2) ((threes++));; # 以此類(lèi)推说榆。
  3) ((fours++));;
  4) ((fives++));;
  5) ((sixes++));;
esac
}

echo


while [ "$throw" -lt "$MAXTHROWS" ]
do
  let "die1 = RANDOM % $PIPS"
  update_count $die1
  let "throw += 1"
done

print_result

exit $?

#  假設(shè) RANDOM 是真隨機(jī)虚吟,那么計(jì)數(shù)結(jié)果應(yīng)該均勻分布。
#  當(dāng) $MAXTHROWS 的值為 600 時(shí)签财,每一個(gè)計(jì)數(shù)器的值都應(yīng)該在 100 左右串慰,
#+ 上下浮動(dòng)大約 20。
#
#  記住 RANDOM 是一個(gè) ***偽隨機(jī)*** 生成器唱蒸,
#+ 并且也不是其中最優(yōu)秀的那一個(gè)邦鲫。

#  隨機(jī)化是一個(gè)很深?yuàn)W且復(fù)雜的話題。
#  足夠長(zhǎng)的“隨機(jī)”序列可能會(huì)出現(xiàn)一些
#+ 混亂或其他非隨機(jī)化的表現(xiàn)神汹。

# 練習(xí)(簡(jiǎn)單):
# ---------------
# 重寫(xiě)腳本庆捺,修改為投擲硬幣 1000 次古今。
# 顯示為正面 "HEADS" 和背面 "TAILS"。

從上一個(gè)樣例中我們可以發(fā)現(xiàn)滔以,在每次調(diào)用 RANDOM 生成器時(shí)捉腥,最好利用重置生成器種子
在 RANDOM 生成器中使用相同的種子會(huì)生成相同序列的隨機(jī)數(shù)。(與 C 語(yǔ)言中的 random() 函數(shù)的行為一致)

樣例-6. 重置 RANDOM 種子

#!/bin/bash
# seeding-random.sh: 設(shè)置 RANDOM 變量的種子醉者。
# 版本號(hào) 1.1, 發(fā)布日期 09 Feb 2013

MAXCOUNT=25       # 生成隨機(jī)數(shù)的個(gè)數(shù)但狭。
SEED=

random_numbers ()
{
local count=0
local number

while [ "$count" -lt "$MAXCOUNT" ]
do
  number=$RANDOM
  echo -n "$number "
  let "count++"
done
}

echo; echo

SEED=1
RANDOM=$SEED      # 設(shè)置變量 RANDOM 會(huì)為隨機(jī)數(shù)生成器設(shè)置種子。
echo "Random seed = $SEED"
random_numbers

RANDOM=$SEED      # 同樣的種子 ...
echo; echo "Again, with same random seed ..."
echo "Random seed = $SEED"
random_numbers    # ... 生成了同樣的數(shù)字序列撬即。
                  #
                  # 在什么情況下重復(fù)一個(gè)隨機(jī)化序列會(huì)有用立磁?

echo; echo

SEED=2
RANDOM=$SEED      # 用不同的種子再試一次 ...
echo "Random seed = $SEED"
random_numbers    # ... 生成了不同的數(shù)字序列。

echo; echo

# RANDOM=$$  利用腳本的進(jìn)程 ID 設(shè)置 RANDOM 的種子剥槐。
# 同樣也可以利用 'time' 或是 'date' 命令設(shè)置 RANDOM 的種子唱歧。

# 更花哨一點(diǎn)的 ...
SEED=$(head -1 /dev/urandom | od -N 1 | awk '{ print $2 }'| sed s/^0*//)
#  從 /dev/urandom (系統(tǒng)的偽隨機(jī)設(shè)備文件)中
#+ 獲取偽隨機(jī)輸出,
#+ 然后通過(guò) "od" 轉(zhuǎn)換為可打印八進(jìn)制字符行粒竖,
#+ 然后 "awk" 命令會(huì)檢索出一個(gè)數(shù)字作為種子颅崩,
#+ 最后用 "sed" 命令刪除數(shù)字前面所有的前置 0。
RANDOM=$SEED
echo "Random seed = $SEED"
random_numbers

echo; echo

exit 0

偽設(shè)備文件 /dev/urandom 提供了比 $RANDOM 變量更隨機(jī)化的偽隨機(jī)數(shù)蕊苗。命令 dd if=/dev/urandom of=targetfile bs=1 count=XXX 將會(huì)創(chuàng)建一個(gè)包含均勻分布的偽隨機(jī)數(shù)的文件沿后。但是想要在腳本中將這些隨機(jī)數(shù)賦值給變量需要做一些變通,比如使用命令 od 或者使用管道導(dǎo)入命令 md5sum

當(dāng)然也有其他在腳本中生成偽隨機(jī)數(shù)的方法
比如: Awk 命令就提供了這樣一種非常簡(jiǎn)易的方法

樣例-7. 使用 awk 命令生成偽隨機(jī)數(shù)

#!/bin/bash
#  random2.sh: 返回大小在 0 - 1 內(nèi)朽砰,
#+ 精度為小數(shù)點(diǎn)后 6 位的偽隨機(jī)數(shù)尖滚。例如:0.822725
#  使用 awk rand() 函數(shù)。

AWKSCRIPT=' { srand(); print rand() } '
#           傳遞給 awk 的命令或參數(shù)
# 注意 srand() 重置了 awk 的隨機(jī)數(shù)生成種子瞧柔。


echo -n "Random number between 0 and 1 = "

echo | awk "$AWKSCRIPT"
# 如果省略 'echo' 將會(huì)發(fā)生什么漆弄?

exit 0


# 練習(xí):
# ---------

# 1) 使用循環(huán)結(jié)構(gòu),輸出 10 個(gè)不同的隨機(jī)數(shù)造锅。
#      (提示:你必須在每次循環(huán)中使用 srand() 函數(shù)重置種子以獲得不同的隨機(jī)數(shù)種子撼唾。
#+       如果你省略了這一步會(huì)發(fā)生什么?)

# 2) 利用整型乘數(shù)作為隨機(jī)數(shù)的縮放因子哥蔚,
#+   生成大小在 10 到 100 之間的隨機(jī)數(shù)倒谷。

# 3) 內(nèi)容與練習(xí) #2 相同,只是這次生成隨機(jī)整數(shù)肺素。

同樣恨锚,命令 date可以用于 生成整型隨機(jī)數(shù)序列

注記

  • 真正的“隨機(jī)性”,就其存在而言倍靡,只存在于一些類(lèi)似放射性衰變這樣還未被完全理解的自然現(xiàn)象中猴伶,計(jì)算機(jī)只能模擬這樣的隨機(jī)性,因此計(jì)算機(jī)生成的“隨機(jī)數(shù)”序列被稱作偽隨機(jī)數(shù)办桨。

  • 計(jì)算機(jī)用于生成偽隨機(jī)數(shù)的種子可以被視作一個(gè)標(biāo)識(shí)標(biāo)簽呢撞。例如: 你可以將用種子 23 生成的隨機(jī)數(shù)序列視作第23號(hào)序列摧阅。
    偽隨機(jī)數(shù)序列的一個(gè)屬性是該序列在開(kāi)始重復(fù)之前的周期長(zhǎng)度祝钢,一個(gè)好的偽隨機(jī)數(shù)生成器能夠生成周期非常長(zhǎng)的序列。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市肃晚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌吧碾,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抄瑟,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)萝毛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)略荡,“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了储矩?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)洁仗。 經(jīng)常有香客問(wèn)我,道長(zhǎng)性锭,這世上最難降的妖魔是什么草冈? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任拳恋,我火速辦了婚禮伞访,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘滑废。我一直安慰自己,他們只是感情好蠕趁,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布俺陋。 她就那樣靜靜地躺著豁延,像睡著了一般。 火紅的嫁衣襯著肌膚如雪腊状。 梳的紋絲不亂的頭發(fā)上诱咏,一...
    開(kāi)封第一講書(shū)人閱讀 51,208評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音缴挖,去河邊找鬼袋狞。 笑死,一個(gè)胖子當(dāng)著我的面吹牛映屋,可吹牛的內(nèi)容都是我干的苟鸯。 我是一名探鬼主播,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼棚点,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼早处!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起瘫析,我...
    開(kāi)封第一講書(shū)人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤砌梆,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后贬循,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體咸包,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年甘有,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了诉儒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡亏掀,死狀恐怖忱反,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情滤愕,我是刑警寧澤温算,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站间影,受9級(jí)特大地震影響注竿,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜魂贬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一巩割、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧付燥,春花似錦宣谈、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)漩怎。三九已至,卻和暖如春嗦嗡,著一層夾襖步出監(jiān)牢的瞬間勋锤,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工侥祭, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留叁执,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓卑硫,卻偏偏與公主長(zhǎng)得像徒恋,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子欢伏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容