10.4. Операторы выбора | Популярный Linux

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


Инструкции case и select технически не являются циклами, поскольку не предусматривают многократное исполнение блока кода. Однако, они, как и циклы, управляют ходом исполнения программы, в зависимости от начальных или конечных условий.

case (in) /
esac

Конструкция case эквивалентна конструкции switch в языке C/C++. Она позволяет выполнять тот или иной участок кода, в зависимости от результатов проверки условий. Она является, своего рода, краткой формой записи большого количества операторов if/then/else и может быть неплохим инструментом при создании разного рода меню.

case «$variable» in

 «$condition1» )
 command
 ;;

 «$condition2» )
 command
 ;;

esac

Note
  • Заключать переменные в кавычки необязательно, поскольку здесь не производится разбиения на отдельные слова.

  • Каждая строка с условием должна завершаться правой (закрывающей) круглой скобкой ).

  • Каждый блок команд, отрабатывающих по заданному условию, должен завершаться двумя символами точка-с-запятой ;;.

  • Блок case должен завершаться ключевым словом esac (case записанное в обратном порядке).

Пример 10-24. Использование case

  1. #!/bin/bash
  2. echo; echo «Нажмите клавишу и затем клавишу Return.»
  3. read Keypress
  4. case «$Keypress« in
  5.   [a-z]   ) echo «буква в нижнем регистре»;;
  6.   [A-Z]   ) echo «Буква в верхнем регистре»;;
  7.   [09]   ) echo «Цифра»;;
  8.   *       ) echo «Знак пунктуации, пробел или что-то другое»;;
  9. esac  # Допускается указыватль диапазоны символов в [квадратных скобках].
  10. # Упражнение:
  11. # ———
  12. # Сейчас сценарий считывает нажатую клавишу и завершается.
  13. # Измените его так, чтобы сценарий продолжал отвечать на нажатия клавиш,
  14. # но завершался бы только после ввода символа «X».
  15. # Подсказка: заключите все в цикл «while».
  16. exit 0

Пример 10-25. Создание меню с помощью case

  1. #!/bin/bash
  2. # Грубый пример базы данных
  3. clear # Очистка экрана
  4. echo »          Список»
  5. echo »          ——«
  6. echo «Выберите интересующую Вас персону:»
  7. echo
  8. echo «[E]vans, Roland»
  9. echo «[J]ones, Mildred»
  10. echo «[S]mith, Julie»
  11. echo «[Z]ane, Morris»
  12. echo
  13. read person
  14. case «$person« in
  15. # Обратите внимание: переменная взята в кавычки.
  16.   «E» | «e» )
  17.   # Пользователь может ввести как заглавную, так и строчную букву.
  18.   echo
  19.   echo «Roland Evans»
  20.   echo «4321 Floppy Dr.»
  21.   echo «Hardscrabble, CO 80753»
  22.   echo «(303) 734-9874»
  23.   echo «(303) 734-9892 fax»
  24.   echo «revans@zzy.net»
  25.   echo «Старый друг и партнер по бизнесу»
  26.   ;;
  27. # Обратите внимание: блок кода, анализирующий конкретный выбор, завершается
  28. # двумя символами «точка-с-запятой».
  29.   «J» | «j» )
  30.   echo
  31.   echo «Mildred Jones»
  32.   echo «249 E. 7th St., Apt. 19»
  33.   echo «New York, NY 10009»
  34.   echo «(212) 533-2814»
  35.   echo «(212) 533-9972 fax»
  36.   echo «milliej@loisaida.com»
  37.   echo «Подружка»
  38.   echo «День рождения: 11 февраля»
  39.   ;;
  40. # Информация о Smith и Zane будет добавлена позднее.
  41.           * )
  42.    # Выбор по-умолчанию.
  43.    # «Пустой» ввод тоже обрабатывается здесь.
  44.    echo
  45.    echo «Нет данных.»
  46.   ;;
  47. esac
  48. echo
  49. #  Упражнение:
  50. #  ———
  51. #  Измените этот сценарий таким образом, чтобы он не завершал работу
  52. #+ после вывода информации о персоне, а переходил на ожидание нового
  53. #+ ввода от пользователя.
  54. exit 0

Очень хороший пример использования case для анализа аргументов, переданных из командной строки.

  1. #! /bin/bash
  2. case «$1» in
  3. «») echo «Порядок использования: ${0##*/} <filename>»; exit 65;;  # Параметры командной строки отсутствуют,
  4.                                                   # или первый параметр — «пустой».
  5. # Обратите внимание на ${0##*/} это подстановка параметра ${var##pattern}. В результате получается $0.
  6. *) FILENAME=./$1;;   # Если имя файла (аргумент $1) начинается с «-«,
  7.                       # то заменить его на ./$1
  8.                       # тогда параметр не будет восприниматься как ключ команды.
  9. * ) FILENAME=$1;;     # В противном случае — $1.
  10. esac

Пример 10-26. Оператор case допускает использовать подстановку команд вместо анализируемой переменной

  1. #!/bin/bash
  2. # Подстановка команд в «case».
  3. case $( arch ) in # команда «arch» возвращает строку, описывающую аппаратную апхитектуру.
  4. i386 ) echo «Машина на базе процессора 80386»;;
  5. i486 ) echo «Машина на базе процессора 80486»;;
  6. i586 ) echo «Машина на базе процессора Pentium»;;
  7. i686 ) echo «Машина на базе процессора Pentium2 или выше»;;
  8. *    ) echo «Машина на другом типе процессора»;;
  9. esac
  10. exit 0

Оператор case допускает использование шаблонных конструкций.

Пример 10-27. Простой пример сравнения строк

  1. #!/bin/bash
  2. # match-string.sh: простое сравнение строк
  3. match_string ()
  4. {
  5.   MATCH=0
  6.   NOMATCH=90
  7.   PARAMS=2     # Функция требует два входных аргумента.
  8.   BAD_PARAMS=91
  9.   [ $# -eq $PARAMS ] || return $BAD_PARAMS
  10.   case «$1» in
  11.   «$2») return $MATCH;;
  12.   *   ) return $NOMATCH;;
  13.   esac
  14. }
  15. a=one
  16. b=two
  17. c=three
  18. d=two
  19. match_string $a     # неверное число аргументов
  20. echo $?             # 91
  21. match_string $a $b  # не равны
  22. echo $?             # 90
  23. match_string $b $d  # равны
  24. echo $?             # 0
  25. exit 0

Пример 10-28. Проверка ввода

  1. #!/bin/bash
  2. # isalpha.sh: Использование «case» для анализа строк.
  3. SUCCESS=0
  4. FAILURE=-1
  5. isalpha ()  # Проверка — является ли первый символ строки символом алфавита.
  6. {
  7. if [ -z «$1» ]                # Вызов функции без входного аргумента?
  8. then
  9.   return $FAILURE
  10. fi
  11. case «$1» in
  12. [a-zA-Z]*) return $SUCCESS;;  # Первый символ — буква?
  13. *        ) return $FAILURE;;
  14. esac
  15. }             # Сравните с функцией «isalpha ()» в языке C.
  16. isalpha2 ()   # Проверка — состоит ли вся строка только из символов алфавита.
  17. {
  18.   [ $# -eq 1 ] || return $FAILURE
  19.   case $1 in
  20.   *[!a-zA-Z]*|«») return $FAILURE;;
  21.                *) return $SUCCESS;;
  22.   esac
  23. }
  24. isdigit ()    # Проверка — состоит ли вся строка только из цифр.
  25. {             # Другими словами — является ли строка целым числом.
  26.   [ $# -eq 1 ] || return $FAILURE
  27.   case $1 in
  28.   *[!09]*|«») return $FAILURE;;
  29.             *) return $SUCCESS;;
  30.   esac
  31. }
  32. check_var ()  # Интерфейс к isalpha
  33. {
  34. if isalpha «$@»
  35. then
  36.   echo «$* начинается с алфавитного символа.»
  37.   if isalpha2 «$@»
  38.   then        # Дальнейшая проверка не имеет смысла, если первй символ не буква.
  39.     echo «$* содержит только алфавитные символы.»
  40.   else
  41.     echo «$* содержит по меньшей мере один не алфавитный символ.»
  42.   fi
  43. else
  44.   echo «$* начинсется с не алфавитного символа .»
  45.               #  Если функция вызвана без входного параметра,
  46.               #+ то считается, что строка содержит «не алфавитной» символ.
  47. fi
  48. echo
  49. }
  50. digit_check ()  # Интерфейс к isdigit ().
  51. {
  52. if isdigit «$@»
  53. then
  54.   echo «$* содержит только цифры [0 — 9].»
  55. else
  56.   echo «$* содержит по меньшей мере один не цифровой символ.»
  57. fi
  58. echo
  59. }
  60. a=23skidoo
  61. b=H3llo
  62. c=-What?
  63. d=What?
  64. e=`echo $b`   # Подстановка команды.
  65. f=AbcDef
  66. g=27234
  67. h=27a34
  68. i=27.34
  69. check_var $a
  70. check_var $b
  71. check_var $c
  72. check_var $d
  73. check_var $e
  74. check_var $f
  75. check_var     # Вызов без параметра, что произойдет?
  76. #
  77. digit_check $g
  78. digit_check $h
  79. digit_check $i
  80. exit 0        # Сценарий дополнен S.C.
  81. # Упражнение:
  82. # ———
  83. #  Напишите функцию ‘isfloat ()’, которая проверяла бы вещественные числа.
  84. #  Подсказка: Эта функция подобна функции ‘isdigit ()’,
  85. #+ надо лишь добавить анализ наличия десятичной точки.
select

Оператор select был заимствован из Korn Shell, и является еще одним инструментом, используемым при создании меню.

select variable [in list]
do
 command
 break
done

Этот оператор предлагает пользователю выбрать один из представленных вариантов. Примечательно, что select по-умолчанию использует в качестве приглашения к вводу (prompt) — PS3 (#? ), который легко изменить.

Пример 10-29. Создание меню с помощью select

  1. #!/bin/bash
  2. PS3=‘Выберите ваш любимый овощ: ‘ # строка приглашения к вводу (prompt)
  3. echo
  4. select vegetable in «бобы» «морковь» «картофель» «лук» «брюква»
  5. do
  6.   echo
  7.   echo «Вы предпочитаете $vegetable
  8.   echo «;-))»
  9.   echo
  10.   break  # если ‘break’ убрать, то получится бесконечный цикл.
  11. done
  12. exit 0

Если в операторе select список in list не задан, то в качестве списка будет использоваться список аргументов ($@), передаваемый сценарию или функции.

Сравните это с поведением оператора цикла

for variable [in list]

в котором не задан
список аргументов.

Пример 10-30. Создание меню с помощью select в функции

  1. #!/bin/bash
  2. PS3=‘Выберите ваш любимый овощ: ‘
  3. echo
  4. choice_of()
  5. {
  6. select vegetable
  7. # список выбора [in list] отсутствует, поэтому ‘select’ использует входные аргументы функции.
  8. do
  9.   echo
  10.   echo «Вы предпочитаете $vegetable
  11.   echo «;-))»
  12.   echo
  13.   break
  14. done
  15. }
  16. choice_of бобы рис морковь редис томат шпинат
  17. #         $1   $2  $3      $4    $5    $6
  18. #         передача списка выбора в функцию choice_of()
  19. exit 0

См. так же Пример 34-3.

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