case和select结构在技术上说并不是循环, 因为它们并不对可执行代码块进行迭代. 但是和循环相似的是, 它们也依靠在代码块顶部或底部的条件判断来决定程序的分支. 



在代码块中控制程序分支 



case (in) / esac 



    在shell中的case结构与C/C++中的switch结构是相同的. 它允许通过判断来选择代码块中多条路径中的一条. 它的作用和多个if/then/else语句的作用相同, 是它们的简化结构, 特别适用于创建菜单.

Ruby代码  
  1. case  "$variable"  in
  2. "$condition1"  )
  3. command...
  4. ;;
  5. "$condition2"  )
  6. command...
  7. ;;
  8. esac
  9. Note





          对变量使用""并不是强制的, 因为不会发生单词分割. 

        * 



          每句测试行, 都以右小括号)来结尾. 

        * 



          每个条件判断语句块都以一对分号结尾 ;;. 

        * 



          case块以esac (case的反向拼写)结尾. 



    例子 10-24. 使用case

Ruby代码  
  1. #!/bin/bash
  2. # 测试字符串范围.
  3. echo; echo "Hit a key, then hit return."
  4. read Keypress
  5. case  "$Keypress"  in
  6. [[:lower :]]   ) echo "Lowercase letter" ;;
  7. [[:upper :]]   ) echo "Uppercase letter" ;;
  8. [0-9]         ) echo "Digit" ;;
  9. *             ) echo "Punctuation, whitespace, or other" ;;
  10. esac      #  允许字符串的范围出现在[中括号]中,
  11. #+ 或者出现在POSIX风格的[[双中括号中.
  12. #  在这个例子的第一个版本中,
  13. #+ 测试大写和小写字符串的工作使用的是
  14. #+ [a-z] 和 [A-Z].
  15. #  这种用法在某些特定场合的或某些Linux发行版中不能够正常工作.
  16. #  POSIX 的风格更具可移植性.
  17. #  感谢Frank Wang指出了这点.
  18. #  练习:
  19. #  -----
  20. #  就像这个脚本所表现出来的, 它只允许单次的按键, 然后就结束了.
  21. #  修改这个脚本, 让它能够接受重复输入,
  22. #+ 报告每次按键, 并且只有在"X"被键入时才结束.
  23. #  暗示: 将这些代码都用"while"循环圈起来.
  24. exit 0

例子 10-25. 使用case来创建菜单

Ruby代码  
  1. #!/bin/bash
  2. # 未经处理的地址资料
  3. clear # 清屏.
  4. echo "          Contact List"
  5. echo "          ------- ----"
  6. echo "Choose one of the following persons:"
  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 "Business partner & old friend"
  26. ;;
  27. # 注意, 每个选项后边都要以双分号;;结尾.
  28. "J"  | "j"  )
  29. echo
  30. echo "Mildred Jones"
  31. echo "249 E. 7th St., Apt. 19"
  32. echo "New York, NY 10009"
  33. echo "(212) 533-2814"
  34. echo "(212) 533-9972 fax"
  35. echo "milliej@loisaida.com"
  36. echo "Ex-girlfriend"
  37. echo "Birthday: Feb. 11"
  38. ;;
  39. # 后边的 Smith 和 Zane 的信息在这里就省略了.
  40. * )
  41. # 默认选项.
  42. # 空输入(敲回车RETURN), 也适用于这里.
  43. echo
  44. echo "Not yet in database."
  45. ;;
  46. esac
  47. echo
  48. #  练习:
  49. #  -----
  50. #  修改这个脚本, 让它能够接受多个输入,
  51. #+ 并且能够显示多个地址.
  52. exit 0

一个case的非常聪明的用法, 用来测试命令行参数.

Ruby代码  
  1. #! /bin/bash
  2. case  "$1"  in
  3. "" ) echo "Usage: ${0##*/} <filename>" ; exit $E_PARAM ;;  # 没有命令行参数,
  4. # 或者第一个参数为空.
  5. # 注意: ${0##*/} 是 ${var##pattern} 的一种替换形式. 得到的结果为$0.
  6. -*) FILENAME=./$1 ;;   #  如果传递进来的文件名参数($1)以一个破折号开头,
  7. #+ 那么用./$1来代替.
  8. #+ 这样后边的命令将不会把它作为一个选项来解释.
  9. * ) FILENAME=$1 ;;     # 否则, $1.
  10. esac

这是一个命令行参数处理的更容易理解的例子:

Ruby代码  
  1. #! /bin/bash
  2. while  [ $# -gt 0 ]; do    # 直到你用完所有的参数 . . .
  3. case  "$1"  in
  4. -d|--debug)
  5. # 是 "-d" 或 "--debug" 参数?
  6. DEBUG=1
  7. ;;
  8. -c|--conf)
  9. CONFFILE="$2"
  10. shift
  11. if  [ ! -f $CONFFILE  ]; then
  12. echo "Error: Supplied file doesn't exist!"
  13. exit $E_CONFFILE      # 错误: 文件未发现.
  14. fi
  15. ;;
  16. esac
  17. shift       # 检查剩余的参数.
  18. done
  19. #  来自Stefano Falsetto的 "Log2Rot" 脚本,
  20. #+ 并且是他的"rottlog"包的一部分.
  21. #  已得到使用许可.

例子 10-26. 使用命令替换来产生case变量

Ruby代码  
  1. #!/bin/bash
  2. # case-cmd.sh: 使用命令替换来产生"case"变量.
  3. case  $( arch ) in    # "arch" 返回机器体系的类型.
  4. # 等价于 'uname -m' ...
  5. i386 ) echo "80386-based machine" ;;
  6. i486 ) echo "80486-based machine" ;;
  7. i586 ) echo "Pentium-based machine" ;;
  8. i686 ) echo "Pentium2+-based machine" ;;
  9. *    ) echo "Other type of machine" ;;
  10. esac
  11. exit 0

case结构也可以过滤通配(globbing)模式的字符串. 



    例子 10-27. 简单的字符串匹配

Ruby代码  
  1. #!/bin/bash
  2. # match-string.sh: 简单的字符串匹配
  3. match_string ()
  4. {
  5. MATCH=0
  6. NOMATCH=90
  7. PARAMS=2     # 此函数需要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. 检查输入字符是否为字母

Ruby代码  
  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. }             # 同C语言的"isalpha ()"函数比较一下.
  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. *[!0-9]*|"" ) return  $FAILURE ;;
  29. *) return  $SUCCESS ;;
  30. esac
  31. }
  32. check_var ()  # 测试isalpha().
  33. {
  34. if  isalpha "$@"
  35. then
  36. echo "/"$*/" begins with an alpha character."
  37. if  isalpha2 "$@"
  38. then         # 不需要测试第一个字符是否是non-alpha.
  39. echo "/"$*/" contains only alpha characters."
  40. else
  41. echo "/"$*/" contains at least one non-alpha character."
  42. fi
  43. else
  44. echo "/"$*/" begins with a non-alpha character."
  45. # 如果没有参数传递进来, 也是"non-alpha".
  46. fi
  47. echo
  48. }
  49. digit_check ()  # 测试isdigit().
  50. {
  51. if  isdigit "$@"
  52. then
  53. echo "/"$*/" contains only digits [0 - 9]."
  54. else
  55. echo "/"$*/" has at least one non-digit character."
  56. fi
  57. echo
  58. }
  59. a=23skidoo
  60. b=H3llo
  61. c=-What?
  62. d=What?
  63. e=`echo $b `   # 命令替换.
  64. f=AbcDef
  65. g=27234
  66. h=27a34
  67. i=27.34
  68. check_var $a
  69. check_var $b
  70. check_var $c
  71. check_var $d
  72. check_var $e
  73. check_var $f
  74. check_var     # 没有参数传递进来, 将会发生什么?
  75. #
  76. digit_check $g
  77. digit_check $h
  78. digit_check $i
  79. exit 0        # S.C改进了这个脚本.

# 练习: 

     # ----- 

     #  编写一个'isfloat ()'函数来测试浮点数. 

     #  暗示: 这个函数基本上与'isdigit ()'相同, 

     #+ 但是要添加一些小数点部分的处理. 



select 



    select结构是建立菜单的另一种工具, 这种结构是从ksh中引入的. 



    select variable [in list] 

    do 

     command... 

    燽reak 

    done 



    提示用户输入选择的内容(比如放在变量列表中). 注意: select命令使用PS3提示符, 默认为(#?), 当然, 这可以修改. 



    例子 10-29. 使用select来创建菜单

Ruby代码  
  1. #!/bin/bash
  2. PS3='Choose your favorite vegetable: '  # 设置提示符字串.
  3. echo
  4. select vegetable in  "beans"  "carrots"  "potatoes"  "onions" "rutabagas"
  5. do
  6. echo
  7. echo "Your favorite veggie is $vegetable."
  8. echo "Yuck!"
  9. echo
  10. break   # 如果这里没有 'break' 会发生什么?
  11. done
  12. exit 0

如果忽略了in list列表, 那么select命令将会使用传递到脚本的命令行参数($@), 或者是函数参数(当select是在函数中时). 



    与忽略in list的 



    for variable [in list] 

    结构比较一下. 



    例子 10-30. 使用函数中的select结构来创建菜单

Ruby代码  
  1. #!/bin/bash
  2. PS3='Choose your favorite vegetable: '
  3. echo
  4. choice_of()
  5. {
  6. select vegetable
  7. # [in list]被忽略, 所以'select'使用传递给函数的参数.
  8. do
  9. echo
  10. echo "Your favorite veggie is $vegetable."
  11. echo "Yuck!"
  12. echo
  13. break
  14. done
  15. }
  16. choice_of beans rice carrots radishes tomatoes spinach
  17. #         $1    $2   $3      $4       $5       $6
  18. #         传递给choice_of()的参数
  19. exit 0

shell脚本学习之case例子的更多相关文章

  1. shell脚本学习之case用法及实例

    case语句和判断语句[if...elif...else]功能类似;当在逻辑判断比较简单的情况下,比后者的代码量要少许多.case用法,用变量来匹配某值,如果匹配成功则执行它下面的命令,直到 ;;为止 ...

  2. Shell 脚本学习资料搜集

    Shell文档 ChinaUnix上大神“網中人”总结的Shell十三问,强烈推荐,这本书讲得比较精炼,而且都是一些Shell学习中容易把握不住的一些细节难点.每一问都写得非常精彩.ChinaUnix ...

  3. Shell脚本学习指南笔记

    Shell脚本学习指南 作者:Danbo 2015-8-3 脚本编程语言与编译型语言的差异 许多中型.大型的程序都是用编译型语言写的,例如:C.C+.Java等.这类程序只要从源代码(Source C ...

  4. shell脚本学习之6小时搞定(1)

    shell脚本学习之6小时搞定(1) 简介 Shell是一种脚本语言,那么,就必须有解释器来执行这些脚本. Unix/Linux上常见的Shell脚本解释器有bash.sh.csh.ksh等,习惯上把 ...

  5. 笔记——shell脚本学习指南

    <shell脚本学习指南>机械工业出版 ISBN 987-7-111-25504-8 第2章 2.4 初级陷阱 1.当今的系统,对#!这一行的长度限制从63到1024个字符都有,尽量不要超 ...

  6. 学习笔记之Shell脚本学习指南 & sed与awk & 正则表达式

    正则表达式_百度百科 http://baike.baidu.com/link?url=ybgDrN2WQQKN64_gu-diCqdeDqL8LQ-jiQ-ftzzPaNUa9CmgBRDNnyx50 ...

  7. 转 shell脚本学习指南

    shell脚本学习指南 以下八点不敢说就能成为你shell脚本学习指南de全部,至少可以让你编写出可靠的shell脚本. 1. 指定bashshell 脚本的第一行,#!之后应该是什么?如果拿这个问题 ...

  8. Shell脚本学习 - 运算符

    继续shell脚本学习.上一篇是基本数据类型和语法的总结,这一篇是运算相关的操作. 运算符 bash不支持简单的数学计算,需要依赖其他命令实现. expr可以代为实现. # 表达式一般这么写 ` + ...

  9. shell脚本学习总结02--数组

    bash同时支持普通数组个关联数组,普通数组只能使用整数作为数组的索引,关联数组可以使用字符串作为数组的索引. 数组的定义方法: 在单行中使用一列值定义一个数组 [root@new ~]# array ...

随机推荐

  1. wcf 请考虑增加操作超时

    发送到 net.tcp://192.168.1.18:8732/CallbackService 的请求操作在配置的超时(00:00:59.9879994)内未收到回复. 分配给此操作的时间可能已经是更 ...

  2. Ubuntu 桌面歌词

    Ubuntu 有个用来显示歌词软件叫 osd-lyrics. 这个软件的强大之处在于他可以和各种播放器配合, 并且可以自动下载歌词. 自从升级到14.04后不能用了,便以为该软件被废弃了. 无意中发现 ...

  3. Spark RCFile的那些“坑”

    RCFile在平台的应用场景中多数用于存储需要“长期留存”的数据文件,在我们的实践过程中,RCFile的数据压缩比通常可以达到8 : 1或者10 : 1,特别适用于存储用户通过Hive(MapRedu ...

  4. 【狼】unity3d 怎样在一定时间连按两下键

    public class DoubleClick : MonoBehaviour { ; void Update() { if (Input.GetKeyDown(KeyCode.D)) { if ( ...

  5. Unity之Avatar原理

    今天花了一些时间理了理Unity的动画系统. 之前给不同模型配动画时没怎么在意,只知道用Avatar可以让一个模型使用另一个模型的动画.由于用的基本上都是人物模型,基本上没出现什么错误. 不过在用到异 ...

  6. 关于OC头文件互相引用的问题

    在OC中头文件互相引用是很常见的一件事,如: A的头文件#import "B.h" 而B的头文件#import "A.h" 这个时候就会出现意想不到的问题.系统 ...

  7. 基础排序算法之并归排序(Merge Sort)

    并归排序是学习分治法 (Merge Sort) 的好例子.而且它相对于选择,插入,冒泡排序来说,算法性能有一定提升.我首先会描述要解决的问题,并给出一个并归排序的例子.之后是算法的思路以及给出伪代码. ...

  8. C++Primer第5版学习笔记(三)

    C++Primer第5版学习笔记(三) 第四/五章的重难点内容           你可以点击这里回顾第三章内容       因为第五章的内容比较少,因此和第四章的笔记内容合并.       第四章是 ...

  9. 利用qemu模拟嵌入式系统制作全过程

    http://www.tinylab.org/using-qemu-simulation-inserts-the-type-system-to-produce-the-whole-process/ 利 ...

  10. 【转】java 文件 读取目录下的所有文件(包括子目录)

    转自:http://www.cnblogs.com/pricks/archive/2009/11/11/1601044.html import java.io.File; import java.io ...