⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 randomvar.html

📁 一本完整的描述Unix Shell 编程的工具书的所有范例
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><HTML><HEAD><TITLE>$RANDOM: generate random integer</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.57"><LINKREL="HOME"TITLE="Advanced Bash-Scripting Guide"HREF="index.html"><LINKREL="UP"TITLE="Variables Revisited"HREF="variables2.html"><LINKREL="PREVIOUS"TITLE="Indirect References to Variables"HREF="ivr.html"><LINKREL="NEXT"TITLE="The Double Parentheses Construct"HREF="dblparens.html"><METAHTTP-EQUIV="Content-Style-Type"CONTENT="text/css"><LINKREL="stylesheet"HREF="common/kde-common.css"TYPE="text/css"><METAHTTP-EQUIV="Content-Type"CONTENT="text/html; charset=iso-8859-1"><METAHTTP-EQUIV="Content-Language"CONTENT="en"><LINKREL="stylesheet"HREF="common/kde-localised.css"TYPE="text/css"TITLE="KDE-English"><LINKREL="stylesheet"HREF="common/kde-default.css"TYPE="text/css"TITLE="KDE-Default"></HEAD><BODYCLASS="SECT1"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#AA0000"VLINK="#AA0055"ALINK="#AA0000"STYLE="font-family: sans-serif;"><DIVCLASS="NAVHEADER"><TABLEWIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">Advanced Bash-Scripting Guide: An in-depth exploration of the art of shell scripting</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="ivr.html">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">Chapter 9. Variables Revisited</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="dblparens.html">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1"><ANAME="RANDOMVAR">9.6. $RANDOM: generate random integer</A></H1><P><TTCLASS="VARNAME">$RANDOM</TT> is an internal Bash <AHREF="functions.html#FUNCTIONREF">function</A> (not a constant) that	  returns a <ICLASS="FIRSTTERM">pseudorandom</I>	    <ANAME="AEN5174"HREF="#FTN.AEN5174">[1]</A>	  integer in the range 0 - 32767. It should	  <TTCLASS="REPLACEABLE"><I>not</I></TT> be used to generate an encryption	  key.</P><DIVCLASS="EXAMPLE"><HR><ANAME="EX21"></A><P><B>Example 9-24. Generating random numbers</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;#!/bin/bash   2&nbsp;   3&nbsp;# $RANDOM returns a different random integer at each invocation.   4&nbsp;# Nominal range: 0 - 32767 (signed 16-bit integer).   5&nbsp;   6&nbsp;MAXCOUNT=10   7&nbsp;count=1   8&nbsp;   9&nbsp;echo  10&nbsp;echo "$MAXCOUNT random numbers:"  11&nbsp;echo "-----------------"  12&nbsp;while [ "$count" -le $MAXCOUNT ]      # Generate 10 ($MAXCOUNT) random integers.  13&nbsp;do  14&nbsp;  number=$RANDOM  15&nbsp;  echo $number  16&nbsp;  let "count += 1"  # Increment count.  17&nbsp;done  18&nbsp;echo "-----------------"  19&nbsp;  20&nbsp;# If you need a random int within a certain range, use the 'modulo' operator.  21&nbsp;# This returns the remainder of a division operation.  22&nbsp;  23&nbsp;RANGE=500  24&nbsp;  25&nbsp;echo  26&nbsp;  27&nbsp;number=$RANDOM  28&nbsp;let "number %= $RANGE"  29&nbsp;#           ^^  30&nbsp;echo "Random number less than $RANGE  ---  $number"  31&nbsp;  32&nbsp;echo  33&nbsp;  34&nbsp;  35&nbsp;  36&nbsp;#  If you need a random integer greater than a lower bound,  37&nbsp;#+ then set up a test to discard all numbers below that.  38&nbsp;  39&nbsp;FLOOR=200  40&nbsp;  41&nbsp;number=0   #initialize  42&nbsp;while [ "$number" -le $FLOOR ]  43&nbsp;do  44&nbsp;  number=$RANDOM  45&nbsp;done  46&nbsp;echo "Random number greater than $FLOOR ---  $number"  47&nbsp;echo  48&nbsp;  49&nbsp;   # Let's examine a simple alternative to the above loop, namely  50&nbsp;   #       let "number = $RANDOM + $FLOOR"  51&nbsp;   # That would eliminate the while-loop and run faster.  52&nbsp;   # But, there might be a problem with that. What is it?  53&nbsp;  54&nbsp;  55&nbsp;  56&nbsp;# Combine above two techniques to retrieve random number between two limits.  57&nbsp;number=0   #initialize  58&nbsp;while [ "$number" -le $FLOOR ]  59&nbsp;do  60&nbsp;  number=$RANDOM  61&nbsp;  let "number %= $RANGE"  # Scales $number down within $RANGE.  62&nbsp;done  63&nbsp;echo "Random number between $FLOOR and $RANGE ---  $number"  64&nbsp;echo  65&nbsp;  66&nbsp;  67&nbsp;  68&nbsp;# Generate binary choice, that is, "true" or "false" value.  69&nbsp;BINARY=2  70&nbsp;T=1  71&nbsp;number=$RANDOM  72&nbsp;  73&nbsp;let "number %= $BINARY"  74&nbsp;#  Note that    let "number &#62;&#62;= 14"    gives a better random distribution  75&nbsp;#+ (right shifts out everything except last binary digit).  76&nbsp;if [ "$number" -eq $T ]  77&nbsp;then  78&nbsp;  echo "TRUE"  79&nbsp;else  80&nbsp;  echo "FALSE"  81&nbsp;fi    82&nbsp;  83&nbsp;echo  84&nbsp;  85&nbsp;  86&nbsp;# Generate a toss of the dice.  87&nbsp;SPOTS=6   # Modulo 6 gives range 0 - 5.  88&nbsp;          # Incrementing by 1 gives desired range of 1 - 6.  89&nbsp;          # Thanks, Paulo Marcel Coelho Aragao, for the simplification.  90&nbsp;die1=0  91&nbsp;die2=0  92&nbsp;# Would it be better to just set SPOTS=7 and not add 1? Why or why not?  93&nbsp;  94&nbsp;# Tosses each die separately, and so gives correct odds.  95&nbsp;  96&nbsp;    let "die1 = $RANDOM % $SPOTS +1" # Roll first one.  97&nbsp;    let "die2 = $RANDOM % $SPOTS +1" # Roll second one.  98&nbsp;    #  Which arithmetic operation, above, has greater precedence --  99&nbsp;    #+ modulo (%) or addition (+)? 100&nbsp; 101&nbsp; 102&nbsp;let "throw = $die1 + $die2" 103&nbsp;echo "Throw of the dice = $throw" 104&nbsp;echo 105&nbsp; 106&nbsp; 107&nbsp;exit 0</PRE></TD></TR></TABLE><HR></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="PICKCARD"></A><P><B>Example 9-25. Picking a random card from a deck</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;#!/bin/bash   2&nbsp;# pick-card.sh   3&nbsp;   4&nbsp;# This is an example of choosing random elements of an array.   5&nbsp;   6&nbsp;   7&nbsp;# Pick a card, any card.   8&nbsp;   9&nbsp;Suites="Clubs  10&nbsp;Diamonds  11&nbsp;Hearts  12&nbsp;Spades"  13&nbsp;  14&nbsp;Denominations="2  15&nbsp;3  16&nbsp;4  17&nbsp;5  18&nbsp;6  19&nbsp;7  20&nbsp;8  21&nbsp;9  22&nbsp;10  23&nbsp;Jack  24&nbsp;Queen  25&nbsp;King  26&nbsp;Ace"  27&nbsp;  28&nbsp;# Note variables spread over multiple lines.  29&nbsp;  30&nbsp;  31&nbsp;suite=($Suites)                # Read into array variable.  32&nbsp;denomination=($Denominations)  33&nbsp;  34&nbsp;num_suites=${#suite[*]}        # Count how many elements.  35&nbsp;num_denominations=${#denomination[*]}  36&nbsp;  37&nbsp;echo -n "${denomination[$((RANDOM%num_denominations))]} of "  38&nbsp;echo ${suite[$((RANDOM%num_suites))]}  39&nbsp;  40&nbsp;  41&nbsp;# $bozo sh pick-cards.sh  42&nbsp;# Jack of Clubs  43&nbsp;  44&nbsp;  45&nbsp;# Thank you, "jipe," for pointing out this use of $RANDOM.  46&nbsp;exit 0</PRE></TD></TR></TABLE><HR></DIV><P>	<ICLASS="EMPHASIS">Jipe</I> points out a set of techniques for	generating random numbers within a range.	<TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;#  Generate random number between 6 and 30.   2&nbsp;   rnumber=$((RANDOM%25+6))	   3&nbsp;   4&nbsp;#  Generate random number in the same 6 - 30 range,   5&nbsp;#+ but the number must be evenly divisible by 3.   6&nbsp;   rnumber=$(((RANDOM%30/3+1)*3))   7&nbsp;   8&nbsp;#  Note that this will not work all the time.   9&nbsp;#  It fails if $RANDOM returns 0.  10&nbsp;  11&nbsp;#  Frank Wang suggests the following alternative:  12&nbsp;   rnumber=$(( RANDOM%27/3*3+6 ))</PRE></TD></TR></TABLE>	</P><P>	<ICLASS="EMPHASIS">Bill Gradwohl</I> came up with an improved	formula that works for positive numbers.	<TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;rnumber=$(((RANDOM%(max-min+divisibleBy))/divisibleBy*divisibleBy+min))</PRE></TD></TR></TABLE>	</P><P>Here Bill presents a versatile function that returns	  a random number between two specified values.</P><DIVCLASS="EXAMPLE"><HR><ANAME="RANDOMBETWEEN"></A><P><B>Example 9-26. Random between values</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;#!/bin/bash   2&nbsp;# random-between.sh   3&nbsp;# Random number between two specified values.    4&nbsp;# Script by Bill Gradwohl, with minor modifications by the document author.   5&nbsp;# Used with permission.   6&nbsp;   7&nbsp;   8&nbsp;randomBetween() {   9&nbsp;   #  Generates a positive or negative random number  10&nbsp;   #+ between $min and $max  11&nbsp;   #+ and divisible by $divisibleBy.  12&nbsp;   #  Gives a "reasonably random" distribution of return values.  13&nbsp;   #  14&nbsp;   #  Bill Gradwohl - Oct 1, 2003  15&nbsp;  16&nbsp;   syntax() {  17&nbsp;   # Function embedded within function.  18&nbsp;      echo  19&nbsp;      echo    "Syntax: randomBetween [min] [max] [multiple]"  20&nbsp;      echo  21&nbsp;      echo    "Expects up to 3 passed parameters, but all are completely optional."  22&nbsp;      echo    "min is the minimum value"  23&nbsp;      echo    "max is the maximum value"  24&nbsp;      echo    "multiple specifies that the answer must be a multiple of this value."  25&nbsp;      echo    "    i.e. answer must be evenly divisible by this number."  26&nbsp;      echo      27&nbsp;      echo    "If any value is missing, defaults area supplied as: 0 32767 1"  28&nbsp;      echo    "Successful completion returns 0, unsuccessful completion returns"  29&nbsp;      echo    "function syntax and 1."  30&nbsp;      echo    "The answer is returned in the global variable randomBetweenAnswer"  31&nbsp;      echo    "Negative values for any passed parameter are handled correctly."  32&nbsp;   }  33&nbsp;  34&nbsp;   local min=${1:-0}  35&nbsp;   local max=${2:-32767}  36&nbsp;   local divisibleBy=${3:-1}  37&nbsp;   # Default values assigned, in case parameters not passed to function.  38&nbsp;  39&nbsp;   local x  40&nbsp;   local spread  41&nbsp;  42&nbsp;   # Let's make sure the divisibleBy value is positive.  43&nbsp;   [ ${divisibleBy} -lt 0 ] &#38;&#38; divisibleBy=$((0-divisibleBy))  44&nbsp;  45&nbsp;   # Sanity check.  46&nbsp;   if [ $# -gt 3 -o ${divisibleBy} -eq 0 -o  ${min} -eq ${max} ]; then   47&nbsp;      syntax  48&nbsp;      return 1  49&nbsp;   fi  50&nbsp;  51&nbsp;   # See if the min and max are reversed.  52&nbsp;   if [ ${min} -gt ${max} ]; then  53&nbsp;      # Swap them.  54&nbsp;      x=${min}  55&nbsp;      min=${max}  56&nbsp;      max=${x}  57&nbsp;   fi  58&nbsp;  59&nbsp;   #  If min is itself not evenly divisible by $divisibleBy,  60&nbsp;   #+ then fix the min to be within range.  61&nbsp;   if [ $((min/divisibleBy*divisibleBy)) -ne ${min} ]; then   62&nbsp;      if [ ${min} -lt 0 ]; then  63&nbsp;         min=$((min/divisibleBy*divisibleBy))  64&nbsp;      else  65&nbsp;         min=$((((min/divisibleBy)+1)*divisibleBy))  66&nbsp;      fi  67&nbsp;   fi  68&nbsp;  69&nbsp;   #  If max is itself not evenly divisible by $divisibleBy,  70&nbsp;   #+ then fix the max to be within range.  71&nbsp;   if [ $((max/divisibleBy*divisibleBy)) -ne ${max} ]; then   72&nbsp;      if [ ${max} -lt 0 ]; then  73&nbsp;         max=$((((max/divisibleBy)-1)*divisibleBy))  74&nbsp;      else  75&nbsp;         max=$((max/divisibleBy*divisibleBy))  76&nbsp;      fi  77&nbsp;   fi  78&nbsp;  79&nbsp;   #  ---------------------------------------------------------------------  80&nbsp;   #  Now, to do the real work.  81&nbsp;  82&nbsp;   #  Note that to get a proper distribution for the end points,  83&nbsp;   #+ the range of random values has to be allowed to go between  84&nbsp;   #+ 0 and abs(max-min)+divisibleBy, not just abs(max-min)+1.  85&nbsp;  86&nbsp;   #  The slight increase will produce the proper distribution for the  87&nbsp;   #+ end points.  88&nbsp;  89&nbsp;   #  Changing the formula to use abs(max-min)+1 will still produce  90&nbsp;   #+ correct answers, but the randomness of those answers is faulty in  91&nbsp;   #+ that the number of times the end points ($min and $max) are returned  92&nbsp;   #+ is considerably lower than when the correct formula is used.  93&nbsp;   #  ---------------------------------------------------------------------  94&nbsp;  95&nbsp;   spread=$((max-min))  96&nbsp;   [ ${spread} -lt 0 ] &#38;&#38; spread=$((0-spread))  97&nbsp;   let spread+=divisibleBy  98&nbsp;   randomBetweenAnswer=$(((RANDOM%spread)/divisibleBy*divisibleBy+min))     99&nbsp; 100&nbsp;   return 0 101&nbsp; 102&nbsp;   #  However, Paulo Marcel Coelho Aragao points out that 103&nbsp;   #+ when $max and $min are not divisible by $divisibleBy, 104&nbsp;   #+ the formula fails. 105&nbsp;   # 106&nbsp;   #  He suggests instead the following formula: 107&nbsp;   #    rnumber = $(((RANDOM%(max-min+1)+min)/divisibleBy*divisibleBy)) 108&nbsp; 109&nbsp;} 110&nbsp; 111&nbsp;# Let's test the function. 112&nbsp;min=-14 113&nbsp;max=20 114&nbsp;divisibleBy=3 115&nbsp; 116&nbsp; 117&nbsp;#  Generate an array of expected answers and check to make sure we get 118&nbsp;#+ at least one of each answer if we loop long enough. 119&nbsp; 120&nbsp;declare -a answer 121&nbsp;minimum=${min} 122&nbsp;maximum=${max} 123&nbsp;   if [ $((minimum/divisibleBy*divisibleBy)) -ne ${minimum} ]; then  124&nbsp;      if [ ${minimum} -lt 0 ]; then 125&nbsp;         minimum=$((minimum/divisibleBy*divisibleBy)) 126&nbsp;      else 127&nbsp;         minimum=$((((minimum/divisibleBy)+1)*divisibleBy)) 128&nbsp;      fi 129&nbsp;   fi 130&nbsp; 131&nbsp; 132&nbsp;   #  If max is itself not evenly divisible by $divisibleBy, 133&nbsp;   #+ then fix the max to be within range. 134&nbsp; 135&nbsp;   if [ $((maximum/divisibleBy*divisibleBy)) -ne ${maximum} ]; then  136&nbsp;      if [ ${maximum} -lt 0 ]; then 137&nbsp;         maximum=$((((maximum/divisibleBy)-1)*divisibleBy)) 138&nbsp;      else 139&nbsp;         maximum=$((maximum/divisibleBy*divisibleBy)) 140&nbsp;      fi 141&nbsp;   fi 142&nbsp; 143&nbsp; 144&nbsp;#  We need to generate only positive array subscripts, 145&nbsp;#+ so we need a displacement that that will guarantee 146&nbsp;#+ positive results.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -