case和select结构在技术上说并不是循环, 因为它们并不对可执行代码块进行迭代. 但是和循环相似的是, 它们也依靠在代码块顶部或底部的条件判断来决定程序的分支.
在代码块中控制程序分支
case (in) / esac
在shell中的case结构与C/C++中的switch结构是相同的. 它允许通过判断来选择代码块中多条路径中的一条. 它的作用和多个if/then/else语句的作用相同, 是它们的简化结构, 特别适用于创建菜单.
- case "$variable" in
-
- "$condition1" )
- command...
- ;;
-
- "$condition2" )
- command...
- ;;
-
- esac
- Note
*
对变量使用""并不是强制的, 因为不会发生单词分割.
*
每句测试行, 都以右小括号)来结尾.
*
每个条件判断语句块都以一对分号结尾 ;;.
*
case块以esac (case的反向拼写)结尾.
例子 10-24. 使用case
-
-
-
- echo; echo "Hit a key, then hit return."
- read Keypress
-
- case "$Keypress" in
- [[:lower :]] ) echo "Lowercase letter" ;;
- [[:upper :]] ) echo "Uppercase letter" ;;
- [0-9] ) echo "Digit" ;;
- * ) echo "Punctuation, whitespace, or other" ;;
- esac
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- exit 0
例子 10-25. 使用case来创建菜单
-
-
-
-
- clear
-
- echo " Contact List"
- echo " ------- ----"
- echo "Choose one of the following persons:"
- 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 "Business partner & old friend"
- ;;
-
-
- "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 "Ex-girlfriend"
- echo "Birthday: Feb. 11"
- ;;
-
-
-
- * )
-
-
- echo
- echo "Not yet in database."
- ;;
-
- esac
-
- echo
-
-
-
-
-
-
- exit 0
一个case的非常聪明的用法, 用来测试命令行参数.
-
-
- case "$1" in
- "" ) echo "Usage: ${0##*/} <filename>" ; exit $E_PARAM ;; # 没有命令行参数,
-
-
-
- -*) FILENAME=./$1 ;;
-
-
-
- * ) FILENAME=$1 ;;
- esac
这是一个命令行参数处理的更容易理解的例子:
-
-
-
- while [ $
- case "$1" in
- -d|--debug)
-
- DEBUG=1
- ;;
- -c|--conf)
- CONFFILE="$2"
- shift
- if [ ! -f $CONFFILE ]; then
- echo "Error: Supplied file doesn't exist!"
- exit $E_CONFFILE
- fi
- ;;
- esac
- shift
- done
-
-
-
-
例子 10-26. 使用命令替换来产生case变量
-
-
-
- case $( arch ) in
-
- i386 ) echo "80386-based machine" ;;
- i486 ) echo "80486-based machine" ;;
- i586 ) echo "Pentium-based machine" ;;
- i686 ) echo "Pentium2+-based machine" ;;
- * ) echo "Other type of machine" ;;
- esac
-
- exit 0
case结构也可以过滤通配(globbing)模式的字符串.
例子 10-27. 简单的字符串匹配
-
-
-
- match_string ()
- {
- MATCH=0
- NOMATCH=90
- PARAMS=2
- BAD_PARAMS=91
-
- [ $
-
- case "$1" in
- "$2" ) return $MATCH ;;
- * ) return $NOMATCH ;;
- esac
-
- }
-
-
- a=one
- b=two
- c=three
- d=two
-
-
- match_string $a
- echo $?
-
- match_string $a $b
- echo $?
-
- match_string $b $d
- echo $?
-
-
- exit 0
例子 10-28. 检查输入字符是否为字母
-
-
-
- SUCCESS=0
- FAILURE=-1
-
- isalpha ()
- {
- if [ -z "$1" ]
- then
- return $FAILURE
- fi
-
- case "$1" in
- [a-zA-Z]*) return $SUCCESS ;;
- * ) return $FAILURE ;;
- esac
- }
-
-
- isalpha2 ()
- {
- [ $
-
- case $1 in
- *[!a-zA-Z]*|"" ) return $FAILURE ;;
- *) return $SUCCESS ;;
- esac
- }
-
- isdigit ()
- {
- [ $
-
- case $1 in
- *[!0-9]*|"" ) return $FAILURE ;;
- *) return $SUCCESS ;;
- esac
- }
-
-
-
- check_var ()
- {
- if isalpha "$@"
- then
- echo "/"$*/" begins with an alpha character."
- if isalpha2 "$@"
- then
- echo "/"$*/" contains only alpha characters."
- else
- echo "/"$*/" contains at least one non-alpha character."
- fi
- else
- echo "/"$*/" begins with a non-alpha character."
-
- fi
-
- echo
-
- }
-
- digit_check ()
- {
- if isdigit "$@"
- then
- echo "/"$*/" contains only digits [0 - 9]."
- else
- echo "/"$*/" has at least one non-digit character."
- 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
# 练习:
# -----
# 编写一个'isfloat ()'函数来测试浮点数.
# 暗示: 这个函数基本上与'isdigit ()'相同,
#+ 但是要添加一些小数点部分的处理.
select
select结构是建立菜单的另一种工具, 这种结构是从ksh中引入的.
select variable [in list]
do
command...
燽reak
done
提示用户输入选择的内容(比如放在变量列表中). 注意: select命令使用PS3提示符, 默认为(#?), 当然, 这可以修改.
例子 10-29. 使用select来创建菜单
-
-
- PS3='Choose your favorite vegetable: '
-
- echo
-
- select vegetable in "beans" "carrots" "potatoes" "onions" "rutabagas"
- do
- echo
- echo "Your favorite veggie is $vegetable."
- echo "Yuck!"
- echo
- break
- done
-
- exit 0
如果忽略了in list列表, 那么select命令将会使用传递到脚本的命令行参数($@), 或者是函数参数(当select是在函数中时).
与忽略in list的
for variable [in list]
结构比较一下.
例子 10-30. 使用函数中的select结构来创建菜单
-
-
- PS3='Choose your favorite vegetable: '
-
- echo
-
- choice_of()
- {
- select vegetable
-
- do
- echo
- echo "Your favorite veggie is $vegetable."
- echo "Yuck!"
- echo
- break
- done
- }
-
- choice_of beans rice carrots radishes tomatoes spinach
-
-
-
- exit 0