$ RANDOM - внутрішня функція Bash (НЕ константа), яка повертає псевдовипадкові цілі числа в діапазоні 0 - 32767. Функція $ RANDOM не повинна використовуватися для генерації ключів шифрування.
Приклад 9-23. Генерація випадкових чисел
#! / Bin / bash # $ RANDOM повертає різні випадкові числа при кожному зверненні до неї. # Діапазон зміни: 0 - 32767 (16-бітове ціле зі знаком). MAXCOUNT = 10 count = 1 echo echo "$ MAXCOUNT випадкових чисел:" echo "-----------------" while [ "$ count" -le $ MAXCOUNT] # Генерація 10 ( $ MAXCOUNT) випадкових чисел. do number = $ RANDOM echo $ number let "count + = 1" # Наростити лічильник. done echo "-----------------" # Якщо вам потрібні випадкові числа які не перевищують певного числа, # скористайтеся оператором ділення по модулю (залишок від ділення). RANGE = 500 echo number = $ RANDOM let "number% = $ RANGE" echo "Випадкове число менше $ RANGE --- $ number" echo # Якщо ви бажаєте обмежити діапазон "знизу", # то просто проводите генерацію псевдовипадкових чисел в циклі до Відтоді, # поки не отримаєте число більше нижньої межі. FLOOR = 200 number = 0 # ініціалізація while [ "$ number" -le $ FLOOR] do number = $ RANDOM done echo "Випадкове число, більше $ FLOOR --- $ number" echo # Ці два способи можуть бути скомбіновані. number = 0 #initialize while [ "$ number" -le $ FLOOR] do number = $ RANDOM let "number% = $ RANGE" # Обмеження "зверху" числом $ RANGE. done echo "Випадкове число в діапазоні від $ FLOOR до $ RANGE --- $ number" echo # Генерація випадкових "true" і "false" значень. BINARY = 2 number = $ RANDOM T = 1 let "number% = $ BINARY" # let "number >> = 14" дає більш рівномірний розподіл # (зрушення вправо зміщує старший біт на нульову позицію, інші біти обнуляються). if [ "$ number" -eq $ T] then echo "TRUE" else echo "FALSE" fi echo # Можна імітувати кидання 2-х ігрових кубиків. SPOTS = 7 # залишок від ділення на 7 дає діапазон 0 - 6. ZERO = 0 die1 = 0 die2 = 0 # Кубики "викидаються" окремо. while [ "$ die1" -eq $ ZERO] # Поки на "кубику" нуль. do let "die1 = $ RANDOM% $ SPOTS" # Імітувати кидок першого кубика. done while [ "$ die2" -eq $ ZERO] do let "die2 = $ RANDOM% $ SPOTS" # Імітувати кидок другого кубика. done let "throw = $ die1 + $ die2" echo "Результат кидка кубиків = $ throw" echo exit 0Приклад 9-24. Вибір випадкової карти з колоди
#! / Bin / bash # pick-card.sh # Приклад вибору випадкового елемента масиву. # Вибір випадкової карти з колоди. Suites = "Треф Бубей Черв'яків Пік" Denominations = "2 3 4 5 6 7 8 9 10 Валет Дама Король Туз" suite = ($ Suites) # Ініціалізація масивів. denomination = ($ Denominations) num_suites = $ {# suite [*]} # Кількість елементів масивів. num_denominations = $ {# denomination [*]} echo -n "$ {denomination [$ ((RANDOM% num_denominations))]}" echo $ {suite [$ ((RANDOM% num_suites))]} # $ bozo sh pick- cards.sh # Валет Треф # Спасибі "jipe," за пояснення по роботі з $ RANDOM. exit 0Jipe підказав ще один спосіб генерації випадкових чисел із заданого діапазону.
# Генерація випадкових чисел в діапазоні 6 - 30. rnumber = $ ((RANDOM% 25 + 6)) # Генерується випадкове число з діапазону 6 - 30, # + але при цьому число має ділитися на 3 без залишку. rnumber = $ (((RANDOM% 30/3 + 1) * 3)) # Вправа: Спробуйте розібратися з виразом самостійно.Наскільки випадкові числа, які повертаються функцією $ RANDOM? Кращий спосіб оцінити "випадковість" генеруються чисел - це написати сценарій, який буде імітувати кидання грального кубика досить велике число раз, а потім виведе кількість випадінь кожної з граней ...
Приклад 9-25. Імітація кидання кубика за допомогою RANDOM
#! / Bin / bash # Випадкові чи числа повертає RANDOM? RANDOM = $$ # Ініціалізація генератора випадкових чисел числом PID процесу-сценарію. PIPS = 6 # Кубик має 6 граней. MAXTHROWS = 600 # Можете збільшити, якщо не знаєте куди подіти свого часу. throw = 0 # Лічильник кидків. zeroes = 0 # Обнулити лічильники випадання окремих граней. ones = 0 # тому неініціалізовані змінні - "порожні", і не дорівнюють нулю !. twos = 0 threes = 0 fours = 0 fives = 0 sixes = 0 print_result () {echo echo "одиниць = $ ones" echo "двійок = $ twos" echo "трійок = $ threes" echo "четвірок = $ fours" echo " п'ятірок = $ fives "echo" шісток = $ sixes "echo} update_count () {case" $ 1 "in 0) let" ones + = 1 ";; # 0 відповідає межі "1". 1) let "twos + = 1" ;; # 1 відповідає межі "2", і так далі 2) let "threes + = 1" ;; 3) let "fours + = 1" ;; 4) let "fives + = 1" ;; 5) let "sixes + = 1" ;; esac} echo while [ "$ throw" -lt "$ MAXTHROWS"] do let "die1 = RANDOM% $ PIPS" update_count $ die1 let "throw + = 1" done print_result # Кількість випадінь кожної з граней має бути приблизно однаковим, якщо вважати RANDOM досить випадковим. # Для $ MAXTHROWS = 600, кожна грань повинна випасти приблизно 100 раз (плюс-мінус 20). # # Майте на увазі, що RANDOM - це генератор псевдовипадкових чисел, # Вправа: # --------------- # Перепишіть цей сценарій так, щоб він імітував 1000 кидків монети. # На кожному кидку можливий один з двох варіантів випадання - "ОРЕЛ" або "решка". exit 0Як видно з останнього прикладу, непогано було б виробляти переустановку початкового числа генератора випадкових чисел RANDOM перед тим, як почати роботу з ним. Якщо використовується один і той же початкове число, то генератор RANDOM видаватиме одну і ту ж послідовність чисел. (Це збігається з поведінкою функції random () в мові C.)
Приклад 9-26. перевстановлення RANDOM
#! / Bin / bash # seeding-random.sh: Перевстановлення змінної RANDOM. MAXCOUNT = 25 # Довжина генерується послідовності чисел. random_numbers () {count = 0 while [ "$ count" -lt "$ MAXCOUNT"] do number = $ RANDOM echo -n "$ number" let "count + = 1" done} echo; echo RANDOM = 1 # Перевстановлення початкового числа генератора випадкових чисел RANDOM. random_numbers echo; echo RANDOM = 1 # Те ж саме початкова число ... random_numbers # ... в результаті виходить та сама послідовність чисел. # # В яких випадках може виявитися корисною генерація співпадаючих серій? echo; echo RANDOM = 2 # Ще одна спроба, але з іншим початковим числом ... random_numbers # отримаємо іншу послідовність. echo; echo # RANDOM = $$ в якості початкового числа вибирається PID процесу-сценарію. # Цілком припустимо взяти в якості початкового числа результат роботи команд 'time' або 'date'. # Трохи уяви ... SEED = $ (head -1 / dev / urandom | od -N 1 | awk '{print $ 2}') # Псевдовипадкове число забирається # + з системного генератора псевдовипадкових чисел / dev / urandom, # + потім конвертується в вісімкове число командою "od", # + і нарешті "awk" повертає єдине число для змінної SEED. RANDOM = $ SEED random_numbers echo; echo exit 0Системний генератор / dev / urandom дає послідовність псевдовипадкових чисел з більш рівномірним розподілом, ніж $ RANDOM. Команда dd if = / dev / urandom of = targetfile bs = 1 count = XX створює файл, який містить послідовність псевдовипадкових чисел. Однак, ці числа вимагають додаткової обробки, наприклад за допомогою команди od (Цей прийом використовується в прикладі вище) або dd (Див. приклад 12-42 ).
Є й інші способи генерації псевдовипадкових послідовностей в сценаріях. Awk має для цього достатньо зручні засоби.
Приклад 9-27. Отримання псевдовипадкових чисел за допомогою awk
#! / Bin / bash # random2.sh: Генерація псевдовипадкових чисел в діапазоні 0 - 1. # Використовується функція rand () з awk. AWKSCRIPT = '{srand (); print rand ()} '# Команди / параметри, що передаються awk # Зверніть увагу, функція srand () переустановлює початкове число генератора випадкових чисел. echo -n "Випадкове число в діапазоні від 0 до 1 =" echo | awk "$ AWKSCRIPT" exit 0 # Вправи: # --------- # 1) За допомогою оператора циклу виведіть 10 різних випадкових чисел. # (Підказка: вам буде потрібно викликати функцію "srand ()" # в кожному циклі з різними початковими числами. # Що станеться, якщо цього не зробити?) # 2) Примусьте сценарій генерувати випадкові числа в діапазоні 10 - 100 # використовуючи цілочисельний множник, як коефіцієнт масштабування # 3) Те ж саме, що і в другій вправі, # але на цей раз випадкові числа повинні бути цілими.Наскільки випадкові числа, які повертаються функцією $ RANDOM?Bin / bash # Випадкові чи числа повертає RANDOM?
В яких випадках може виявитися корисною генерація співпадаючих серій?
Що станеться, якщо цього не зробити?