Управляющие конструкции: "case"

Оператор case

http://www.opennet.ru/case

case (in) / esac

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

Ниже приводится формат оператора case:

сase ¨значение¨ in

шаблон_1)

команды_1

..........

шаблон_2)

команды_2

..........

;;

esac

или:

case "$variable" in

"$condition1" )

command...

;;

"$condition2" )

command...

;;

esac




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

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

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

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

Поиск значения, совпадающего с шаблоном, выполняется по каждому шаблону. Если устанавливается соответствие с шаблоном, то оставшиеся шаблоны уже не проверяются. Эти шаблоны не принимаются во внимание даже после выполнения команд, относящихся к шаблону, с которым установлено соответствие. Если поиск соответствия по всем шаблонам оказался безрезультатным, можно принять значение с помощью символа звездочки. Этот символ используется для фиксации любых вводимых данных. Шаблонная часть может содержать метасимволы. Аналогичным образом соответствие с шаблоном устанавливается при обработке расширений имен файлов в командной строке.

  • * Произвольные символы

  • ? Произвольный отдельный символ

  • [...] Произвольный символ из класса или диапазона

Простой оператор case

Следующий сценарий отображает приглашение для ввода чисел от 1 до 5. Число передается оператору case, переменной ANS присваивается значение ANS оператора case, и значение ANS сравнивается с каждым шаблоном. Если соответствие установлено, команды из шаблонной части выполняются до тех пор, пока не появятся символы ;; Тогда на экран выводится команда, которая информирует пользователя о сделанном выборе. Затем выполнение оператора case завершается, поскольку совпадение с шаблоном установлено. Далее выполняются операции, находящиеся после оператора case. Если соответствие не найдено, с помощью шаблона * выполняется прием всей вводимой информации. Затем отображается сообщение об ошибке.

$ pg caseselect

#!/bin/sh

#caseselect

echo -n "enter a number from 1 to 5: "

read ANS

case $ANS in

1) echo "you select 1"

;;

2) echo "you select 2"

;;

3) echo "you select 3"

;;

4) echo "you select 4"

;;

5) echo "you select 5"

;;

*) echo "`basename $0`: This is not between 1 and 5" >&2

exit 1

;;

esac

Итого:

$ caseselect

enter a number from 1 to 5: 4

you select 4

$ caseselect

enter a number from 1 to 5: qwerty

caseselect: This is not between 1 and 5

$

Применение символа pipe ( | ) при поиске по шаблону

При использовании оператора case в качестве команды (or) можно указывать символ канала (pipe |).

Например," vtl00 | vtl02") соответствут шаблону vtl00 или vtl02.

В следующем примере у пользователя запрашивают тип терминала. Если пользователь вводит vt100 или vtl02, выполняется сравнение с шаблоном “vtl00| vtl02>”. В данном случае переменной TERM присваивается значение vtl00. Если пользователь указывает тип терминала, который не соответствует шаблону, с помощью шаблона (*) выполняется прием этой информации и значение типа терминала все равно устанавливается как vt100. Наконец, за пределами действия оператора case производится экспорт переменной TERM.

Независимо от тех сведений, которые вводит пользователь (например ошибочных), переменная TERM представляет TERM=vt100 тип терминала, поскольку используется поиск по шаблону (*) и echo "setting it to vt100 anyway, so there".

$ pg caseterm

#!/bin/sh

# caseterm

echo "choices are.. vt100, vt102, vt220"

echo -n "enter your terminal type: "

read TERMINAL

case $TERMINAL in

vt100 | vt102) TERM=vt100

;;

vt220) TERM=vt220

;;

*) echo "`basename $0` : Unknown response" >&2

echo "setting it to vt100 anyway, so there"

TERM=vt100

;;

esac

export TERM

echo "Your terminal is set to $TERM"

Проверим:

$ caseterm

choices are.. vt100, vt102, vt220

enter your terminal type: vt220

Your terminal is set to vt220

$ caseterm

choices are.. vt100, vt102, vt220

enter your terminal type: qwerty

caseterm : Unknown response

setting it to vt100 anyway, so there

Your terminal is set to vt100

$

Приглашение для ввода Y или N

Оператор case , что очевидно, удобно применять при отображении запроса на продолжение обработки. Ниже приводится сценарий, в котором пользователю предлагается указать в качестве ответа либо ¨у¨, что означает продолжение обработки, либо ¨n¨ — выход из сценария. Если пользователь введет "yes", обработка будет продолжена в соответствии с частью сценария после оператора case. Если пользователь введет "no" или какой-либо другой ответ, работа со сценарием для него завершается.

$ pg caseans

#!/bin/sh

# caseans

echo -n "Do you wish to proceed [y/n]"

read ANS

case $ANS in

y|У|"yes"|Yes)

echo "yes is selected"

;;

n|N|no|No)

echo "no is selected"

exit 0 # нет ошибки, поэтому для выхода укажите 0

;;

*) echo "`basename $0` : Unknown response" >&2

exit 1

;;

esac

Проверим:

$ caseans

Do you wish to proceed [y/n]y

yes is selected

$ caseans

Do you wish to proceed [y/n]n

no is selected

$ caseans

Do you wish to proceed [y/n]jhg

caseans : Unknown response

$

Оператор case и передача системных параметров

Можно также использовать оператор case при передаче параметров в сценарии. В следующем сценарии при осуществлении проверки используется специальный параметр $#, который представляет число передаваемых аргументов. Если это число отлично от 1, сценарий завершает работу, отображая соответствующее сообщение.

Затем оператор case выполняет прием следующих параметров: start, stop или help. В дальнейшем код реализуется для каждого совпадения с этими шаблонами. При передаче неизвестного значения на экран выводится стандартное сообщение об ошибке.

$ pg caseparam

#!/bin/sh

#caseparam

if [ $# != 1 ]; then

echo " $# != 1 Usage: `basename $0` [start|stop|help]" >&2

exit 1

fi

# присвойте переменной ОРТ параметр

OPT=$1

case $OPT in

start) echo "starting..`basename $0`"

# здесь коды для начала процесса

;;

stop) echo "stopping..`basename $0`"

#здесь коды для прекращения процесса

;;

help) echo "help..`basename $0`"

# здесь коды для отображения справочной страницы

;;

*) echo "Usage: `basename $0` [start|stop|help]"

esac

Проверим:

$ caseparam start

starting..caseparam

$ caseparam stop

stopping..caseparam

$ caseparam help

help..caseparam

$ caseparam qwerty

Usage: caseparam [start|stop|help]

$ caseparam

0 != 1 Usage: caseparam [start|stop|help]

$

Прием потока ввода без применения шаблонных команд

После шаблонной части необязательно указывать команды, а возможно использовать шаблонные части для фильтрации нежелательных (ошибочных) откликов.

Предположим существование некого отдела (допустимые номера отдела: 234,453,655,454) в который необходимо отправить определенный отчет ( тип отчета может быть ¨post¨ либо ¨prior¨), сначала желательно удостовериться, что пользователь правильно ввел номер отдела, а затем уже уточнить, какой отчет выполняется. Такой подход реализуется при сравнении с шаблоном всех требуемых значений; любые другие методы неприемлемы.

В следующем сценарии указано, что если пользователь вводит номер отдела, который не совпадает со значением 234, 453, 655 или 454, то пользователь выйдет из сценария. Если номер отдела указан правильно, аналогичный подход применяется при определении типа отчета. По окончании выполнения оператора case остаются действительный номер отдела и правильный тип отчета. Ниже приводится соответствующий сценарий.

$ pg casevalid

#!/bin/sh

# casevalid

TYPE=""

echo -n "enter the account of dept No: "

read ACC

case $ACC in

234) ;;

453) ;;

655) ;;

454) ;;

*) echo "`basename $0`: Unknown dept No:" >&2

echo "try..234,453,655,454"

exit 1

esac

# если оказались здесь, то введен верный номер отдела

echo "1 - post"

echo "2 - prior"

echo -n "enter the type of report: "

read ACC_TYPE

case $ACC_TYPE in

1) TYPE=post ;;

2) TYPE=prior ;;

*) echo "`basename $0`: Unknown account type." >&2

exit 1

;;

esac

# если оказались здесь, то введен верный номер отчета

echo "now running report for dept: \"$ACC\" for the type: \"$TYPE\""

Проверим:

$ casevalid

enter the account of dept No: 234

1 - post

2 - prior

enter the type of report: 1

now running report for dept: "234" for the type: "post"

$ casevalid

enter the account of dept No: 1234567

casevalid: Unknown dept No:

try..234,453,655,454

$ casevalid

enter the account of dept No: 453

1 - post

2 - prior

enter the type of report: 6

casevalid: Unknown account type.

$

Переменные сценария, заданные по "умолчанию"


...Наличие значения переменной (подстановка).

..........................

read WHEN

echo "validating..${WHEN="Saturday"}"

..........................

Следующий пример демонстрирует функционирование оператора case аналогично нескольких операторов if/then else:

$ pg caserep

#!/bin/sh

# caserep

echo " Weekly Report"

echo -n "What day do you want to run report [Saturday] :"

# если нажать клавишу ввода, принимается заданное по умолчанию название Saturday

read WHEN

echo "validating..${WHEN="Saturday"}"

case $WHEN in

Mondaу|MONDAY|mon)

;;

Sunday|SUNDAY|sun)

;;

Saturday|SATURDAY|sat)

;;

*) echo " Are you nuts!, this report can only be run on " >&2

echo " on a Saturday, Sunday or Monday" >&2

exit 1

esac

echo "Report to run on $WHEN"

# здесь команда для выполнения действительного отчета

Проверим:

$ caserep

Weekly Report

What day do you want to run report [Saturday] :----

validating..----

Are you nuts!, this report can only be run on

on a Saturday, Sunday or Monday

$ caserep

Weekly Report

What day do you want to run report [Saturday] :mon

validating..mon

Report to run on mon

$