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. QT的父子Widget之间消息的传递(如果子类没有accept或ignore该事件,则该事件会被传递给其父亲——Qlabel与QPushButton的处理就不一样)

    以前我一直以为:在父widget上摆一个子widget后,当click子widget时:只会进入到子widget的相关事件处理函数中,比如进入到mousePressEvent()中, 而不会进入到父w ...

  2. Tomcat默认打开项目设置

    Tomcat设置默认启动项目 Tomcat设置默认启动项目,顾名思义,就是让可以在浏览器的地址栏中输入ip:8080,就能访问到我们的项目.具体操作如下: 1.打开tomcat的安装根目录,找到Tom ...

  3. mongodb exception in initAndListen: 12596 old lock file, terminating 解决方法

    错误信息如下: exception in initAndListen: 12596 old lock file, terminating 基本上都是由于服务器断电等异常中断重启引起 解决方法 1.删除 ...

  4. codeforce ---A. Milking cows

    A. Milking cows time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...

  5. NHibernate 存储过程使用

    NHibernate也是能够操作存储过程的,不过第一次配置可能会碰到很多错误. 一.删除 首先,我们新建一个存储过程如下: CREATE PROC DeletePerson @Id int AS DE ...

  6. NGUI-学习笔记(2)一个项目需求

    using UnityEngine; using System.Collections; public class ins1 : MonoBehaviour { //bool isTarget = f ...

  7. 0ull 是什么意思?

    unsigned long long 类型的0 同理:#define     DEV_IIC1             ( (u64)1 <<  7ULL)    这个作用是64位中的第7 ...

  8. FPGA入门学习第一课:二分频器

    分频器还是比较简单的,一般的思路是:每数几个时钟就输出一个时钟.最简单的当数二分频器了,每当时钟上升沿(或下降沿)就把输出翻转一下.这样就刚好实现了二分频器了. 网上也搜到了最简实现”二分频最简单了, ...

  9. Best Premium Private Proxy Service | Lime Proxies

    Best Premium Private Proxy Service | Lime Proxies undefined

  10. PHP 下载网络图片

    /* * 功能:php完美实现下载远程图片保存到本地 * 参数:文件url,保存文件目录,保存文件名称,使用的下载方式 * 当保存文件名称为空时则使用远程文件原来的名称 */ function get ...