Книга: Искусство программирования на языке сценариев командной оболочки
10.4. Операторы выбора
Инструкции case и select технически не являются циклами, поскольку не предусматривают многократное исполнение блока кода. Однако, они, как и циклы, управляют ходом исполнения программы, в зависимости от начальных или конечных условий.
case (in) / esac
Конструкция case эквивалентна конструкции switch в языке C/C++. Она позволяет выполнять тот или иной участок кода, в зависимости от результатов проверки условий. Она является, своего рода, краткой формой записи большого количества операторов if/then/else и может быть неплохим инструментом при создании разного рода меню.
case "$variable" in "$condition1" ) command... ;; "$condition2" ) command... ;; esac
?
? Каждая строка с условием должна завершаться правой (закрывающей) круглой скобкой ).
? Каждый блок команд, отрабатывающих по заданному условию, должен завершаться двумя символами точка-с-запятой ;;.
? Блок case должен завершаться ключевым словом esac (case записанное в обратном порядке).
Пример 10-24. Использование case
#!/bin/bash
echo; echo "Нажмите клавишу и затем клавишу Return."
read Keypress
case "$Keypress" in
[a-z] ) echo "буква в нижнем регистре";;
[A-Z] ) echo "Буква в верхнем регистре";;
[0-9] ) echo "Цифра";;
* ) echo "Знак пунктуации, пробел или что-то другое";;
esac # Допускается указыватль диапазоны символов в [квадратных скобках].
# Упражнение:
# --------
# Сейчас сценарий считывает нажатую клавишу и завершается.
# Измените его так, чтобы сценарий продолжал отвечать на нажатия клавиш,
# но завершался бы только после ввода символа "X".
# Подсказка: заключите все в цикл "while".
exit 0
Пример 10-25. Создание меню с помощью case
#!/bin/bash
# Грубый пример базы данных
clear # Очистка экрана
echo " Список"
echo " ------"
echo "Выберите интересующую Вас персону:"
echo
echo "[E]vans, Roland"
echo "[J]ones, Mildred"
echo "[S]mith, Julie"
echo "[Z]ane, Morris"
echo
read person
case "$person" in
# Обратите внимание: переменная взята в кавычки.
"E" | "e" )
# Пользователь может ввести как заглавную, так и строчную букву.
echo
echo "Roland Evans"
echo "4321 Floppy Dr."
echo "Hardscrabble, CO 80753"
echo "(303) 734-9874"
echo "(303) 734-9892 fax"
echo "[email protected]"
echo "Старый друг и партнер по бизнесу"
;;
# Обратите внимание: блок кода, анализирующий конкретный выбор, завершается
# двумя символами "точка-с-запятой".
"J" | "j" )
echo
echo "Mildred Jones"
echo "249 E. 7th St., Apt. 19"
echo "New York, NY 10009"
echo "(212) 533-2814"
echo "(212) 533-9972 fax"
echo "[email protected]"
echo "Подружка"
echo "День рождения: 11 февраля"
;;
# Информация о Smith и Zane будет добавлена позднее.
* )
# Выбор по-умолчанию.
# "Пустой" ввод тоже обрабатывается здесь.
echo
echo "Нет данных."
;;
esac
echo
# Упражнение:
# --------
# Измените этот сценарий таким образом, чтобы он не завершал работу
#+ после вывода информации о персоне, а переходил на ожидание нового
#+ ввода от пользователя.
exit 0
Очень хороший пример использования case для анализа аргументов, переданных из командной строки.
#! /bin/bash
case "$1" in
"") echo "Порядок использования: ${0##*/} <filename>"; exit 65;; # Параметры командной строки отсутствуют,
# или первый параметр -- "пустой".
# Обратите внимание на ${0##*/} это подстановка параметра ${var##pattern}. В результате получается $0.
-*) FILENAME=./$1;; # Если имя файла (аргумент $1) начинается с "-",
# то заменить его на ./$1
# тогда параметр не будет восприниматься как ключ команды.
* ) FILENAME=$1;; # В противном случае -- $1.
esac
Пример 10-26. Оператор case допускает использовать подстановку команд вместо анализируемой переменной
#!/bin/bash
# Подстановка команд в "case".
case $( arch ) in # команда "arch" возвращает строку, описывающую аппаратную апхитектуру.
i386 ) echo "Машина на базе процессора 80386";;
i486 ) echo "Машина на базе процессора 80486";;
i586 ) echo "Машина на базе процессора Pentium";;
i686 ) echo "Машина на базе процессора Pentium2 или выше";;
* ) echo "Машина на другом типе процессора";;
esac
exit 0
Оператор case допускает использование шаблонных конструкций.
Пример 10-27. Простой пример сравнения строк
#!/bin/bash
# match-string.sh: простое сравнение строк
match_string ()
{
MATCH=0
NOMATCH=90
PARAMS=2 # Функция требует два входных аргумента.
BAD_PARAMS=91
[ $# -eq $PARAMS ] || return $BAD_PARAMS
case "$1" in
"$2") return $MATCH;;
* ) return $NOMATCH;;
esac
}
a=one
b=two
c=three
d=two
match_string $a # неверное число аргументов
echo $? # 91
match_string $a $b # не равны
echo $? # 90
match_string $b $d # равны
echo $? # 0
exit 0
Пример 10-28. Проверка ввода
#!/bin/bash
# isalpha.sh: Использование "case" для анализа строк.
SUCCESS=0
FAILURE=-1
isalpha () # Проверка - является ли первый символ строки символом алфавита.
{
if [ -z "$1" ] # Вызов функции без входного аргумента?
then
return $FAILURE
fi
case "$1" in
[a-zA-Z]*) return $SUCCESS;; # Первый символ - буква?
* ) return $FAILURE;;
esac
} # Сравните с функцией "isalpha ()" в языке C.
isalpha2 () # Проверка - состоит ли вся строка только из символов алфавита.
{
[ $# -eq 1 ] || return $FAILURE
case $1 in
*[!a-zA-Z]*|"") return $FAILURE;;
*) return $SUCCESS;;
esac
}
isdigit () # Проверка - состоит ли вся строка только из цифр.
{ # Другими словами - является ли строка целым числом.
[ $# -eq 1 ] || return $FAILURE
case $1 in
*[!0-9]*|"") return $FAILURE;;
*) return $SUCCESS;;
esac
}
check_var () # Интерфейс к isalpha
{
if isalpha "$@"
then
echo ""$*" начинается с алфавитного символа."
if isalpha2 "$@"
then # Дальнейшая проверка не имеет смысла, если первй символ не буква.
echo ""$*" содержит только алфавитные символы."
else
echo ""$*" содержит по меньшей мере один не алфавитный символ."
fi
else
echo ""$*" начинсется с не алфавитного символа ."
# Если функция вызвана без входного параметра,
#+ то считается, что строка содержит "не алфавитной" символ.
fi
echo
}
digit_check () # Интерфейс к isdigit ().
{
if isdigit "$@"
then
echo ""$*" содержит только цифры [0 - 9]."
else
echo ""$*" содержит по меньшей мере один не цифровой символ."
fi
echo
}
a=23skidoo
b=H3llo
c=-What?
d=What?
e=`echo $b` # Подстановка команды.
f=AbcDef
g=27234
h=27a34
i=27.34
check_var $a
check_var $b
check_var $c
check_var $d
check_var $e
check_var $f
check_var # Вызов без параметра, что произойдет?
#
digit_check $g
digit_check $h
digit_check $i
exit 0 # Сценарий дополнен S.C.
# Упражнение:
# --------
# Напишите функцию 'isfloat ()', которая проверяла бы вещественные числа.
# Подсказка: Эта функция подобна функции 'isdigit ()',
#+ надо лишь добавить анализ наличия десятичной точки.
select
Оператор select был заимствован из Korn Shell, и является еще одним инструментом, используемым при создании меню.
select variable [in list] do command... break done
Этот оператор предлагает пользователю выбрать один из представленных вариантов. Примечательно, что select по-умолчанию использует в качестве приглашения к вводу (prompt) -- PS3 (#? ), который легко изменить.
Пример 10-29. Создание меню с помощью select
#!/bin/bash
PS3='Выберите ваш любимый овощ: ' # строка приглашения к вводу (prompt)
echo
select vegetable in "бобы" "морковь" "картофель" "лук" "брюква"
do
echo
echo "Вы предпочитаете $vegetable."
echo ";-))"
echo
break # если 'break' убрать, то получится бесконечный цикл.
done
exit 0
Если в операторе select список in list не задан, то в качестве списка будет использоваться список аргументов ($@), передаваемый сценарию или функции.
Сравните это с поведением оператора цикла
for variable [in list]
в котором не задан список аргументов.
Пример 10-30. Создание меню с помощью select в функции
#!/bin/bash
PS3='Выберите ваш любимый овощ: '
echo
choice_of()
{
select vegetable
# список выбора [in list] отсутствует, поэтому 'select' использует входные аргументы функции.
do
echo
echo "Вы предпочитаете $vegetable."
echo ";-))"
echo
break
done
}
choice_of бобы рис морковь редис томат шпинат
# $1 $2 $3 $4 $5 $6
# передача списка выбора в функцию choice_of()
exit 0
См. так же Пример 34-3.
- Пример 10-24. Использование case
- Пример 10-25. Создание меню с помощью case
- Пример 10-26. Оператор case допускает использовать подстановку команд вместо анализируемой переменной
- Пример 10-27. Простой пример сравнения строк
- Пример 10-28. Проверка ввода
- Пример 10-29. Создание меню с помощью select
- Пример 10-30. Создание меню с помощью select в функции