Глава 34. Bash, версия 2 | Популярный Linux

Опубликовано Bash в Ср, 23/12/2009 — 21:04


Текущая версия Bash, та, которая скорее всего установлена в вашей системе, фактически — 2.XX.Y.

  1. bash$ echo $BASH_VERSION
  2. 2.05.b.0(1)-release
  3.        

В этой версии классического языка сценариев Bash были добавлены
переменные-массивы, [64] расширение строк и подстановка
параметров, улучшен метод косвенных ссылок на
переменные.

Пример 34-1. Расширение строк

  1. #!/bin/bash
  2. # «Расширение» строк (String expansion).
  3. # Введено в Bash, начиная с версии 2.
  4. # Строки вида  $’xxx’
  5. # могут содержать дополнительные экранированные символы.
  6. echo $‘Звонок звенит 3 раза \a \a \a’
  7. echo $‘Три перевода формата \f \f \f’
  8. echo $’10 новых строк \n\n\n\n\n\n\n\n\n\n’
  9. exit 0

Пример 34-2. Косвенные ссылки на переменные — новый метод

  1. #!/bin/bash
  2. # Косвенные ссылки на переменные.
  3. a=letter_of_alphabet
  4. letter_of_alphabet=z
  5. echo «a = $a«           # Прямая ссылка.
  6. echo «Now a = ${!a}«    # Косвенная ссылка.
  7. # Форма записи ${!variable} намного удобнее старой «eval var1=\$$var2»
  8. echo
  9. t=table_cell_3
  10. table_cell_3=24
  11. echo «t = ${!t}«        # t = 24
  12. table_cell_3=387
  13. echo «Значение переменной t изменилось на ${!t}«    # 387
  14. # Теперь их можно использовать для ссылок на элементы массива,
  15. # или для эмуляции многомерных массивов.
  16. # Было бы здорово, если бы косвенные ссылки допускали индексацию.
  17. exit 0

Пример 34-3. Простая база данных, с применением косвенных ссылок

  1. #!/bin/bash
  2. # resistor-inventory.sh
  3. # Простая база данных, с применением косвенных ссылок.
  4. # ============================================================== #
  5. # Данные
  6. B1723_value=470                                   # сопротивление (Ом)
  7. B1723_powerdissip=.25                             # рассеиваемая мощность (Вт)
  8. B1723_colorcode=«желтый-фиолетовый-коричневый»    # цветовая маркировка
  9. B1723_loc=173                                     # где
  10. B1723_inventory=78                                # количество (шт)
  11. B1724_value=1000
  12. B1724_powerdissip=.25
  13. B1724_colorcode=«коричневый-черный-красный»
  14. B1724_loc=24N
  15. B1724_inventory=243
  16. B1725_value=10000
  17. B1725_powerdissip=.25
  18. B1725_colorcode=«коричневый-черный-оранжевый»
  19. B1725_loc=24N
  20. B1725_inventory=89
  21. # ============================================================== #
  22. echo
  23. PS3=‘Введите ноиер: ‘
  24. echo
  25. select catalog_number in «B1723» «B1724» «B1725»
  26. do
  27.   Inv=${catalog_number}_inventory
  28.   Val=${catalog_number}_value
  29.   Pdissip=${catalog_number}_powerdissip
  30.   Loc=${catalog_number}_loc
  31.   Ccode=${catalog_number}_colorcode
  32.   echo
  33.   echo «Номер по каталогу $catalog_number
  34.   echo «Имеется в наличии ${!Inv} шт. [${!Val} Ом / ${!Pdissip} Вт].»
  35.   echo «Находятся в лотке # ${!Loc}
  36.   echo «Цветовая маркировка: ${!Ccode}
  37.   break
  38. done
  39. echo; echo
  40. # Упражнение:
  41. # ———-
  42. # Переделайте этот сценарий так, чтобы он использовал массивы вместо косвенных ссылок.
  43. # Какой из вариантов более простой и интуитивный?
  44. # Примечание:
  45. # ———-
  46. #  Язык командной оболочки не очень удобен для написания приложений,
  47. #+ работающих с базами данных.
  48. #  Для этой цели лучше использовать языки программирования, имеющие
  49. #+ развитые средства для работы со структурами данных,
  50. #+ такие как C++ или Java (может быть Perl).
  51. exit 0

Пример 34-4. Массивы и другие хитрости для раздачи колоды карт в четыре руки

  1. #!/bin/bash
  2. # На старых системах может потребоваться вставить #!/bin/bash2.
  3. # Карты:
  4. # раздача в четыре руки.
  5. UNPICKED=0
  6. PICKED=1
  7. DUPE_CARD=99
  8. LOWER_LIMIT=0
  9. UPPER_LIMIT=51
  10. CARDS_IN_SUIT=13
  11. CARDS=52
  12. declare -a Deck
  13. declare -a Suits
  14. declare -a Cards
  15. # Проще и понятнее было бы, имей мы дело
  16. # с одним 3-мерным массивом.
  17. # Будем надеяться, что в будущем, поддержка многомерных массивов будет введена в Bash.
  18. initialize_Deck ()
  19. {
  20. i=$LOWER_LIMIT
  21. until [ «$i« -gt $UPPER_LIMIT ]
  22. do
  23.   Deck[i]=$UNPICKED   # Пометить все карты в колоде «Deck», как «невыданная».
  24.   let «i += 1»
  25. done
  26. echo
  27. }
  28. initialize_Suits ()
  29. {
  30. Suits[0]# Трефы
  31. Suits[1]# Бубны
  32. Suits[2]# Червы
  33. Suits[3]# Пики
  34. }
  35. initialize_Cards ()
  36. {
  37. Cards=(2 3 4 5 6 7 8 9 10 В Д K Т)
  38. # Альтернативный способ инициализации массива.
  39. }
  40. pick_a_card ()
  41. {
  42. card_number=$RANDOM
  43. let «card_number %= $CARDS«
  44. if [ «${Deck[card_number]}« -eq $UNPICKED ]
  45. then
  46.   Deck[card_number]=$PICKED
  47.   return $card_number
  48. else
  49.   return $DUPE_CARD
  50. fi
  51. }
  52. parse_card ()
  53. {
  54. number=$1
  55. let «suit_number = number / CARDS_IN_SUIT»
  56. suit=${Suits[suit_number]}
  57. echo -n «$suit
  58. let «card_no = number % CARDS_IN_SUIT»
  59. Card=${Cards[card_no]}
  60. printf %-4s $Card
  61. # Вывод по столбцам.
  62. }
  63. seed_random ()  # Переустановка генератора случайных чисел.
  64. {
  65. seed=`eval date +%s`
  66. let «seed %= 32766»
  67. RANDOM=$seed
  68. }
  69. deal_cards ()
  70. {
  71. echo
  72. cards_picked=0
  73. while [ «$cards_picked« -le $UPPER_LIMIT ]
  74. do
  75.   pick_a_card
  76.   t=$?
  77.   if [ «$t« -ne $DUPE_CARD ]
  78.   then
  79.     parse_card $t
  80.     u=$cards_picked+1
  81.     # Возврат к индексации с 1 (временно).
  82.     let «u %= $CARDS_IN_SUIT«
  83.     if [ «$u« -eq 0 ]   # вложенный if/then.
  84.     then
  85.      echo
  86.      echo
  87.     fi
  88.     # Смена руки.
  89.     let «cards_picked += 1»
  90.   fi
  91. done
  92. echo
  93. return 0
  94. }
  95. # Структурное программирование:
  96. # вся логика приложения построена на вызове функций.
  97. #================
  98. seed_random
  99. initialize_Deck
  100. initialize_Suits
  101. initialize_Cards
  102. deal_cards
  103. exit 0
  104. #================
  105. # Упражнение 1:
  106. # Добавьте комментарии, чтобы до конца задокументировать этот сценарий.
  107. # Упражнение 2:
  108. # Исправьте сценарий так, чтобы карты в каждой руке выводились отсортированными по масти.
  109. # Вы можете добавить и другие улучшения.
  110. # Упражнение 3:
  111. # Упростите логику сценария.


[64]    Chet Ramey обещал ввести в Bash ассоциативные массивы (они хорошо знакомы программистам, работающим с языком Perl) в одном из следующих релизов Bash.

Запись опубликована в рубрике Без рубрики. Добавьте в закладки постоянную ссылку.