shell 脚本和case例子

  • Post author:
  • Post category:其他




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