Example 9-25. Generate a random integer
1 #! /Bin/bash 2 3 # each call to $ random will return different random integers. 4 # The general range is 0-32767 (signed 16-bit integer ). 5 6 maxcount = 10 7 COUNT = 1 8 9 echo 10 echo "$ maxcount random numbers: "11 echo" ----------------- "12 while [" $ count "-Le $ maxcount] # generate 10 ($ maxcount) random integers. 13 do 14 number = $ random 15 echo $ number 16 Let "count + = 1" # increase the count. 17 done 18 echo "---------------" 19 20 # If you need to generate a random integer in a specific range, use the 'modulo' (Modulo) operation. (Note: In fact, this is not A very good way. for the reason, see man 3 rand) 21 # The modulo operation returns the remainder of the Division. 22 23 range = 500 24 25 echo 26 27 Number = $ random 28 let "Number % = $ range" 29 # ^ 30 echo "random number less than $ range --- $ number" 31 32 echo 33 34 35 36 # If you need to generate a random integer greater than a lower limit. 37 # + create a test loop to discard all integers smaller than the lower limit. 38 39 floor = 200 40 41 Number = 0 # initialize 42 while ["$ number"-Le $ Floor] 43 do 44 Number = $ random 45 done 46 echo "random number greater $ fl Oor --- $ number "47 echo 48 49 # Let's try a small change to the above loop, as shown below: 50 # Let "number = $ random + $ floor" 51 # This removes the while loop and can run faster. 52 # however, this may cause a problem. What is the problem? 53 54 55 56 # combine the preceding two examples to generate a random number between the specified upper and lower limits. 57 Number = 0 # initialize 58 While ["$ number"-Le $ Floor] 59 do 60 number = $ random 61 let "Number % = $ range" # proportional $ number falls within the range of $ range. 62 done 63 echo "random number between $ floor and $ range --- $ number" 64 echo 65 66 67 68 # generate binary values, that is, "true" or "false" values. 69 binary = 2 70 t = 1 71 Number = $ random 72 73 let "Number % = $ binary" 74 # note that let "number >>= 14" Will Make a better random allocation. # (Note: As mentioned on the man page, higher random distributions are more evenly distributed.) 75 # + (14 digits shifted to the right will clear all the bits, except 15th bits, because it is signed, 16th bits are signed bits ). # The modulo operation uses low positions to generate random numbers, which is relatively uneven) 76 if ["$ number"-EQ $ T] 77 then 78 echo "true" 79 else 80 echo "false" 81 fi 82 83 echo 84 85 86 # Throw a dice. 87 spots = 6 # The value range of mod 6 is 0-5. 88 # If you add 1, the expected range is 1-6. 89 # Thank you, Paulo Marcel Coelho aragao. 90 die1 = 0 91 die2 = 0 92 # Do you want spots = 7 to be better than 1? Can you explain the cause? 93 94 # every time you throw a dice, an equal opportunity will be given. 95 96 let "die1 = $ random % $ spots + 1" # throw the first time. 97 let "die2 = $ random % $ spots + 1" # second throw. 98 # which of the above arithmetic operations has a higher priority? -- 99 # + modulo (%) or addition operation (+ )? 100 101 102 let "Throw = $ die1 + $ die2" 103 echo "throw of the dice = $ throw" 104 echo105 106 exit 0 |
Example 9-26. Take a random card from a playing card
1 #! /Bin/bash 2 # pick-card.sh 3 4 # This is an example of removing random elements from an array. 5 6 7 # extract a card, any card. 8 9 suites = "clubs 10 diamonds 11 hearts 12 spades" 13 14 denominations = "2 15 3 16 4 17 5 18 6 19 7 20 8 21 9 22 10 23 Jack 24 Queen 25 king 26 ace "27 28 # note that multiple rows of the variable are expanded. 29 30 31 suite = ($ suites) # Read an array. 32 denomination = ($ denominations) 33 34 num_suites =$ {# suite [*]} # calculate the number of array elements. 35 num_denominations =$ {# denomination [*]} 36 37 echo-n "$ {denomination [$ (random % num_denominations)]} of "38 echo $ {suite [$ (random % num_suites)]} 39 40 41 # $ bozo sh pick-cards.sh 42 # Jack of Clubs 43 44 45 # Thanks," Jipe, "indicates the usage of $ random. 46 exit 0 |
JipeDemonstrate a set of techniques to generate random numbers within a specified range.
1 # a random number is generated between 6 and 30. 2 rnumber = $ (random % 25 + 6) 3 4 # generate a random number between 6 and 30, and 5 # +, but the number must be divisible by 3. 6 rnumber = $ (random % 30/3 + 1) * 3) 7 8 # note that not all cases can run correctly. 9 # If $ random returns 0, it will fail. 10 11 # the following method is recommended for Frank Wang: 12 rnumber =$ (random % 27/3*3 + 6 )) |
Bill gradwohlAn improved formula is provided, which is only applicable to the main book.
1 rnumber = $ (random % (max-min + divisibleby)/divisibleby * divisibleby + min )) |
Here, bill shows a general formula. This function returns a random number between two specified values.
Example 9-27. Random Number between two specified values
1 #! /Bin/bash 2 # random-between.sh 3 # generate a random number between two specified values. 4 # written by Bill gradwohl, the author of this book made some changes. 5 # The script author is allowed to use it here. 6 7 8 randombetween () {9 # between $ min and $ Max, 10 # + generates a positive or negative random number. 11 # + and can be divisible by $ divisibleby. 12 # Give a reasonable random return value. 13 #14 # Bill gradwohl-Oct 1, 2003 15 16 syntax () {17 # nested function 18 echo 19 echo "Syntax: randombetween [Min] [Max] [multiple] "20 echo 21 echo" expects up to 3 passed parameters, All are completely optional. "22 echo" Min is the minimum value "23 echo" Max is the maximum value "24 echo" multiple specifies that the answer must be a multiple of this value. "25 echo" I. e. answer must be evenly divisible by this number. "26 echo 27 echo" If any value is missing, defaults area supplied as: 0 32767 1 "28 echo" Successful Completion returns 0, unsuccessful completion returns "2 9 echo "function syntax and 1. "30 echo" The answer is returned in the global variable randombetweenanswer "31 echo" negative values for any passed parameter are handled correctly. "32} 33 34 local min =$ {1:-0} 35 local Max =$ {2:-32767} 36 local divisibleby =$ {3: -1} 37 # The default value is allocated to handle situations where no parameters are passed in. 38 39 Local x 40 local spread 41 42 # confirm that divisibleby is positive. 43 [$ {divisibleby}-lt 0] & divisibleby =$ (0-di Visibleby) 44 45 # integrity check. 46 if [$ #-GT 3-o $ {divisibleby}-EQ 0-o $ {min}-EQ $ {max}]; then 47 syntax 48 return 1 49 fi 50 51 # Check whether min and Max are reversed. 52 if [$ {min}-GT $ {max}]; then 53 # switch them. 54 X =$ {min} 55 min =$ {max} 56 Max =$ {x} 57 fi 58 59 # If Min itself cannot be divisible by $ divisibleby, 60 # + adjust the value of Max so that it can be divisible by $ divisibleby, provided that the range cannot be enlarged. 61 if [$ (min/divisibleby * divisibleby)-ne $ {min}]; then 62 if [$ {min} -Lt 0]; then 63 min = $ (min/divisibleby * divisibleby) 64 else 65 min = $ (min/divisibleby) + 1) * divisibleby )) 66 fi 67 fi 68 69 # If Min cannot be divisible by $ divisibleby and 70 # +, adjust the value of Max so that it can be divisible by $ divisibleby, the premise is that the range cannot be enlarged. 71 If [$ (max/divisibleby * divisibleby)-ne $ {max}]; then 72 if [$ {max}-lt 0]; then 73 max = $ (max/divisibleby)-1) * divisibleby) 74 else 75 max = $ (max/divisibleby * divisibleby) 76 fi 77 FI 78 79 # --------------------------------------------------------------------- 80 # Now, let's do some real work. 81 82 # Note: In order to obtain an appropriate distribution for the endpoint, the range of 83 # + random values must be between 84 # + 0 and ABS (max-min) + divisibleby, instead of ABS (max-min) + 1. 85 86 # For the endpoint, 87 # + will generate a suitable allocation. 88 89 # If you modify this formula and use ABS (max-min) + 1 to replace ABS (max-min) + divisibleby, 90 # + will also get the correct answer, however, in this case, the random value generated is not perfect for scenarios where the number of endpoints is equal to 91 # +, because the random rate is low when the number of endpoints is equal to the number of endpoints, 92 # + you only need to add 1, which is much less likely than the normal formula (normally divisibleby ). 93 # define 94 95 spread =$ (max-min) 96 [$ {spread}-lt 0] & spread =$ (0-spread )) 97 let spread + = divisibleby 98 randombetweenanswer = $ (random % spread)/divisibleby * divisibleby + min) 99 100 return 0101 102 # However, paulo Marcel Coelho aragao points out that 103 # + when $ Max and $ min cannot be divisible by $ divisibleby, 104 # + this formula will fail. 105 #106 # The following formula is recommended: 107 # rnumber = $ (random % (max-min + 1) + min)/divisibleby * divisibleby )) 108 109} 110 111 # Let's test this function. 112 min =-14113 max = 20114 divisibleby = 3115 116 117 # generate an expected array answers. The array subscript is used to indicate values that may appear in the range, 118 # + and the element content records the number of occurrences of this value. If we loop many times, we will certainly get at least one chance. 119 120 declare-A answer121 minimum =$ {min} 122 maximum =$ {max} 123 If [$ (minimum/divisibleby * divisibleby)-ne $ {min Imum}]; then 124 If [$ {minimum}-lt 0]; then125 minimum = $ (minimum/divisibleby * divisibleby )) 126 else127 minimum = $ (minimum/divisibleby) + 1) * divisibleby) 128 fi129 fi130 131 132 132 # If max itself cannot be divisible by $ divisibleby, 133 # + adjust the value of Max so that it can be divisible by $ divisibleby, provided that the range cannot be enlarged. 134 135 if [$ (maximum/divisibleby * divisibleby)-ne $ {maximum}]; then 136 If [$ {maximum}-lt 0]; then1_maximum = $ (maximum/d Ivisibleby)-1) * divisibleby) 138 else139 maximum = $ (maximum/divisibleby * divisibleby) 140 fi141 fi142 143 144 # We need to generate an array with all subscripts as positive. 145 # + so we need a displacement, 146 # + to ensure that all results are positive. 147 148 displacement = $ (0-minimum) 149 for (I =$ {minimum}; I <=$ {maximum}; I ++ = divisibleby )); do150 answer [I + displacement] = 0151 done152 153 # Now, let's loop through enough times to get our desired answer. 155 loopit = 1000 # It is recommended that the script author cycle 100000 times, 156 # +, but this is required It's too long. 157 158 for (I = 0; I <$ {loopit}; ++ I); do159 160 # Note: When we call the randombetweenanswer function here, it is estimated that the order of Min and Max will be reversed. 161 # + This is to test whether the function can run correctly in this case. 162 163 randombetween $ {max }$ {min }$ {divisibleby} 164 165 # if the answer is not what we expected, an error is returned. 166 [$ {randombetweenanswer}-lt $ {min}-o $ {randombetweenanswer}-GT $ {max}] & Echo min or max error-$ {randombetweenanswer }! 167 [$ (randombetweenanswer % $ {divisibleby})-Ne 0] & Echo divisible by error-$ {randombetweenanswer }! 168 169 # Save the statistical value to answer. 170 answer [randombetweenanswer + displacement] = $ (answer [randombetweenanswer + displacement] + 1) 171 done172 173 174 # Let's take a look at the results. 176 177 For (I =$ {minimum}; I <=$ {maximum}; I ++ = divisibleby )); do178 [$ {answer [I + displacement]}-EQ 0] & Echo "we never got an answer of $ I. "| echo" $ {I} occurred $ {answer [I + displacement]} Times. "179 done180 181 182 exit 0 |
$ Random
How random is there? The best way is to write a script to test and track$ Random
Generated"Random"Number Distribution. Let's use$ Random
Shake the dice...
Example 9-28. Use a random number to shake a single dice
1 #! /Bin/bash 2 # How random is random? 3 4 random =$ # Use the script process ID as the seed of the random number. 5 6 pips = 6 # A dice has 6 faces. 7. maxthrows = 600 # Add this value if you have nothing to do. 8 throw = 0 # The number of times the dice are thrown. 9 10 ones = 0 # All the Count must be initialized to 0, 11 twos = 0 # + because the uninitialized variable is null, not 0. 12 threes = 0 13 fours = 0 14 fives = 0 15 sixes = 0 16 17 print_result () 18 {19 Echo 20 echo "ones = $ ones" 21 echo "twos = $ Twos" 22 echo "threes = $ threes" 23 echo "fours = $ fours" 24 echo "fives = $ fives "25 echo" sixes = $ sixes "26 echo 27} 28 29 update_count () 30 {31 case "$1" in 32 0) Let "ones + = 1"; # because the dice do not have "zero", give 1. 33 1) Let "twos + = 1"; # Set this parameter to 2, and the same will happen later. 34 2) Let "threes + = 1"; 35 3) Let "fours + = 1"; 36 4) Let "fives + = 1"; 37 5) let "sixes + = 1 ";; 38 esac 39} 40 41 echo 42 43 44 while ["$ throw"-lt "$ maxthrows"] 45 do 46 let "die1 = random % $ pips" 47 update_count $ die1 48 let "Throw + = 1" 49 done 50 51 print_result 52 53 exit 0 54 55 # If random is truly random, the result should be average. 56 # Set $ maxthrows to 600, so each plane should be 100, and the inbound and outbound traffic should not exceed 20. 57 #58 # Remember that random is a pseudo-random number after all. 59 # + is not perfect. 60 61 # The generation of random numbers is a very profound and complex problem. 62 # A long enough random sequence not only shows its chaotic side, but also 63 # + shows its Equal Opportunity side. 64 65 # exercise (very simple): 66 # -------------- 67 # rewrite this script to make it into the form of throwing 1000 coins. 68 # There are two sides: "Header" and "word. |
As we can see in the above example, it is best to generateRandom
Because if the same seed is usedRandom
The same sequence will be generated.[2](CLanguageRandom ()The function also has such behavior .)
Example 9-29. re-allocate Random Seed
1 #! /Bin/bash 2 # seeding-random.sh: Set the random variable as the seed. 3 4 maxcount = 25 # determine how many random numbers are generated. 5 6 random_numbers () 7 {8 count = 0 9 while ["$ count"-lt "$ maxcount"] 10 do 11 Number = $ random 12 echo-n "$ number" 13 Let "count + = 1 "14 done 15} 16 17 echo; echo 18 19 random = 1 # Set the random seed for the generation of random numbers. 20 random_numbers 21 22 echo; echo 23 24 random = 1 # set the same seed... 25 random_numbers #... it will be the same as the random sequence generated above. 26 #27 # copy one Under what circumstances is the same "random" sequence useful? 28 29 echo; echo 30 31 random = 2 # Try again, but use different seeds this time... 32 random_numbers # A different random sequence will be obtained this time. 33 34 echo; echo 35 36 # random =$ $ use the script process ID as the seed to generate random numbers. 37 # It is also common practice to obtain the random as a seed from the 'time' or 'date' command. 38 39 # An imaginative method... 40 seed = $ (Head-1/dev/urandom | OD-N 1 | awk '{print $2 }') 41 # first, extract a row from/dev/urandom (system Pseudo-Random Device File), 42 # +, and then convert the printable row to an octal number, use the "OD" command to convert. 43 # + Finally, use "awk" to obtain a number. 44 # + this number will be used as the seed to generate a random number. 45 random = $ seed 46 random_numbers 47 48 echo; echo 49 50 exit 0 |
|
/Dev/urandomThe device file provides a better way to generate more"Random"Method of random number.Dd If =/dev/urandom of = targetfile BS = 1 COUNT = xxIt can generate a distributed pseudo-random number sequence. however, if you want to assign a value to a variable in a script file, you still need to be operable, such as using the OD command (like the above example, and example 12-13 ), you can also use the DD command (see example 12-55) or pipe it to the md5sum command (see example 33-14 ). Of course there are other methods to generate pseudo-random numbers.AwkYou can provide a convenient method to achieve this. Example 9-30. Use awk to generate a pseudo-random number
1 #! /Bin/bash 2 # random2.sh: generates a pseudo-random number ranging from 0 to 1. 3 # Use the rand () function of awk. 4 5 awkscript = '{srand (); print rand ()}' 6 # command (s)/parameter passed to awk 7 # Note, srand () is a function used in awk to generate pseudo-random number seeds. 8 9 10 echo-n "random number between 0 and 1 =" 11 12 echo | awk "$ awkscript" 13 # What if you save 'echo? 14 15 exit 0 16 17 18 # exercise: 19 # ----- 20 21 #1) print 10 different random numbers using the cyclic structure. 22 # (Note: In each loop, you must use the "srand ()" function to generate different seeds. 23 # + What if you don't do this ?) 24 25 #2) use integer multiplication as a proportional factor. In the range of 10 to 100, 26 # + generates a random number. 27 28 #3) Exercise on the same side #2, but a random integer is generated this time. |
The date command can also be used to generate a pseudo-random integer sequence. |