Перейти к основному содержанию
Рецепты Linux

Main navigation

  • Основы
  • Система
  • Команды
  • Программы
  • Дистро
  • Интерфейсы
  • Устройства
  • Доки
User account menu
  • Войти

Строка навигации

  1. Главная
  2. ABS Guide
  3. Часть 3. Углубленный материал
  4. Глава 10. Циклы и ветвления

10.4. Операторы выбора

Инструкции 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

#!/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 "revans@zzy.net"
 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 "milliej@loisaida.com"
 echo "Подружка"
 echo "День рождения: 11 февраля"
 ;;

# Информация о Smith и Zane будет добавлена позднее.

 * )
 # Выбор по-умолчанию.
 # "Пустой" ввод тоже обрабатывается здесь.
 echo
 echo "Нет данных."
 ;;

esac

echo

# Упражнение:
# --------
# Измените этот сценарий таким образом, чтобы он не завершал работу
#+ после вывода информации о персоне, а переходил на ожидание нового
#+ ввода от пользователя.

exit 0

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

#! /bin/bash

case "$1" in
"") echo "Порядок использования: ${0##*/} "; 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, и является еще одним инструментом, используемым при создании меню.

selectvariable [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 не задан, то в качестве списка будет использоваться список аргументов ($@), передаваемый сценарию или функции.

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

forvariable [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.4. Операторы выбора

  • 10.3. Управление ходом выполнения цикла
  • Вверх
  • Глава 11. Внутренние команды

Book navigation

  • Содержание
  • Часть 1. Введение
  • Часть 2. Основы
  • Часть 3. Углубленный материал
    • Глава 9. К вопросу о переменных
    • Глава 10. Циклы и ветвления
      • 10.1. Циклы
      • 10.2. Вложенные циклы
      • 10.3. Управление ходом выполнения цикла
      • 10.4. Операторы выбора
    • Глава 11. Внутренние команды
    • Глава 12. Внешние команды, программы и утилиты
    • Глава 13. Команды системного администрирования
    • Глава 14. Подстановка команд
    • Глава 15. Арифметические подстановки
    • Глава 16. Перенаправление ввода/вывода
    • Глава 17. Встроенные документы
  • Часть 4. Материал повышенной сложности
  • Глава 35. Замечания и дополнения
  • Библиография
  • Приложение A. Дополнительные примеры сценариев
  • Приложение B. Справочная информация
  • Приложение C. Маленький учебник по Sed и Awk
  • Приложение D. Коды завершения, имеющие предопределенный смысл
  • Приложение E. Подробное введение в операции ввода-вывода и перенаправление ввода-вывода
  • Приложение F. Системные каталоги
  • Приложение G. Локализация
  • Приложение H. История команд
  • Приложение I. Пример файла .bashrc
  • Приложение J. Преобразование пакетных (*.bat) файлов DOS в сценарии командной оболочки
  • Приложение K. Упражнения
  • Приложение L. Хронология
  • Приложение M. Авторские права

Последние материалы

  • Приложение scanimage
    1 day ago
  • Утилита sensors
    5 days ago
  • Сканер Rkhunter
    1 week 6 days ago
  • Программа resize2fs
    2 weeks 4 days ago
  • Аудиопроигрыватель QMMP
    3 weeks 3 days ago
RSS feed

Secondary menu

  • О проекте

© 2008–2025 Олег Меньшенин mensh@yandex.ru