shell 腳本和case例子

轉自:http://hlee.iteye.com/blog/577628

  
case和select結構在技術上說並不是循環, 因爲它們並不對可執行代碼塊進行迭代. 但是和循環相似的是, 它們也依靠在代碼塊頂部或底部的條件判斷來決定程序的分支.

在代碼塊中控制程序分支

case (in) / esac

    在shell中的case結構與C/C++中的switch結構是相同的. 它允許通過判斷來選擇代碼塊中多條路徑中的一條. 它的作用和多個if/then/else語句的作用相同, 是它們的簡化結構, 特別適用於創建菜單.

Ruby代碼  收藏代碼
  1. case  "$variable"  in   
  2.   
  3.  "$condition1"  )  
  4.  command...  
  5.  ;;  
  6.   
  7.  "$condition2"  )  
  8.  command...  
  9.  ;;  
  10.   
  11. esac  
  12. Note     

   

    

        *

          對變量使用""並不是強制的, 因爲不會發生單詞分割.
        *

          每句測試行, 都以右小括號)來結尾.
        *

          每個條件判斷語句塊都以一對分號結尾 ;;.
        *

          case塊以esac (case的反向拼寫)結尾.

    例子 10-24. 使用case

Ruby代碼  收藏代碼
  1. #!/bin/bash   
  2. # 測試字符串範圍.   
  3.   
  4. echo; echo "Hit a key, then hit return."   
  5. read Keypress  
  6.   
  7. case  "$Keypress"  in   
  8.   [[:lower :]]   ) echo "Lowercase letter" ;;  
  9.   [[:upper :]]   ) echo "Uppercase letter" ;;  
  10.   [0-9]         ) echo "Digit" ;;  
  11.   *             ) echo "Punctuation, whitespace, or other" ;;  
  12. esac      #  允許字符串的範圍出現在[中括號]中,   
  13.           #+ 或者出現在POSIX風格的[[雙中括號中.   
  14.   
  15. #  在這個例子的第一個版本中,   
  16. #+ 測試大寫和小寫字符串的工作使用的是   
  17. #+ [a-z] 和 [A-Z].   
  18. #  這種用法在某些特定場合的或某些Linux發行版中不能夠正常工作.   
  19. #  POSIX 的風格更具可移植性.   
  20. #  感謝Frank Wang指出了這點.   
  21.   
  22. #  練習:   
  23. #  -----   
  24. #  就像這個腳本所表現出來的, 它只允許單次的按鍵, 然後就結束了.   
  25. #  修改這個腳本, 讓它能夠接受重複輸入,   
  26. #+ 報告每次按鍵, 並且只有在"X"被鍵入時才結束.   
  27. #  暗示: 將這些代碼都用"while"循環圈起來.   
  28.   
  29. exit 0  



    例子 10-25. 使用case來創建菜單

Ruby代碼  收藏代碼
  1. #!/bin/bash   
  2.   
  3. # 未經處理的地址資料   
  4.   
  5. clear # 清屏.   
  6.   
  7. echo "          Contact List"   
  8. echo "          ------- ----"   
  9. echo "Choose one of the following persons:"   
  10. echo  
  11. echo "[E]vans, Roland"   
  12. echo "[J]ones, Mildred"   
  13. echo "[S]mith, Julie"   
  14. echo "[Z]ane, Morris"   
  15. echo  
  16.   
  17. read person  
  18.   
  19. case  "$person"  in   
  20. # 注意, 變量是被""引用的.   
  21.   
  22.   "E"  | "e"  )  
  23.   # 接受大寫或者小寫輸入.   
  24.   echo  
  25.   echo "Roland Evans"   
  26.   echo "4321 Floppy Dr."   
  27.   echo "Hardscrabble, CO 80753"   
  28.   echo "(303) 734-9874"   
  29.   echo "(303) 734-9892 fax"   
  30.   echo "[email protected]"   
  31.   echo "Business partner & old friend"   
  32.   ;;  
  33. # 注意, 每個選項後邊都要以雙分號;;結尾.   
  34.   
  35.   "J"  | "j"  )  
  36.   echo  
  37.   echo "Mildred Jones"   
  38.   echo "249 E. 7th St., Apt. 19"   
  39.   echo "New York, NY 10009"   
  40.   echo "(212) 533-2814"   
  41.   echo "(212) 533-9972 fax"   
  42.   echo "[email protected]"   
  43.   echo "Ex-girlfriend"   
  44.   echo "Birthday: Feb. 11"   
  45.   ;;  
  46.   
  47. # 後邊的 Smith 和 Zane 的信息在這裏就省略了.   
  48.   
  49.           * )  
  50.    # 默認選項.   
  51.    # 空輸入(敲回車RETURN), 也適用於這裏.   
  52.    echo  
  53.    echo "Not yet in database."   
  54.   ;;  
  55.   
  56. esac  
  57.   
  58. echo  
  59.   
  60. #  練習:   
  61. #  -----   
  62. #  修改這個腳本, 讓它能夠接受多個輸入,   
  63. #+ 並且能夠顯示多個地址.   
  64.   
  65. exit 0  



    一個case的非常聰明的用法, 用來測試命令行參數.

Ruby代碼  收藏代碼
  1. #! /bin/bash   
  2.   
  3. case  "$1"  in   
  4. "" ) echo "Usage: ${0##*/} <filename>" ; exit $E_PARAM ;;  # 沒有命令行參數,  
  5.                                                         # 或者第一個參數爲空.   
  6. # 注意: ${0##*/} 是 ${var##pattern} 的一種替換形式. 得到的結果爲$0.   
  7.   
  8. -*) FILENAME=./$1 ;;   #  如果傳遞進來的文件名參數($1)以一個破折號開頭,   
  9.                       #+ 那麼用./$1來代替.   
  10.                       #+ 這樣後邊的命令將不會把它作爲一個選項來解釋.   
  11.   
  12. * ) FILENAME=$1 ;;     # 否則, $1.   
  13. esac  



    這是一個命令行參數處理的更容易理解的例子:

Ruby代碼  收藏代碼
  1. #! /bin/bash   
  2.   
  3.   
  4. while  [ $# -gt 0 ]; do    # 直到你用完所有的參數 . . .   
  5.   case  "$1"  in   
  6.     -d|--debug)  
  7.               # 是 "-d" 或 "--debug" 參數?   
  8.               DEBUG=1  
  9.               ;;  
  10.     -c|--conf)  
  11.               CONFFILE="$2"   
  12.               shift  
  13.               if  [ ! -f $CONFFILE  ]; then   
  14.                 echo "Error: Supplied file doesn't exist!"   
  15.                 exit $E_CONFFILE      # 錯誤: 文件未發現.   
  16.               fi  
  17.               ;;  
  18.   esac  
  19.   shift       # 檢查剩餘的參數.   
  20. done  
  21.   
  22. #  來自Stefano Falsetto的 "Log2Rot" 腳本,   
  23. #+ 並且是他的"rottlog"包的一部分.   
  24. #  已得到使用許可.   



    例子 10-26. 使用命令替換來產生case變量

Ruby代碼  收藏代碼
  1. #!/bin/bash   
  2. # case-cmd.sh: 使用命令替換來產生"case"變量.   
  3.   
  4. case  $( arch ) in    # "arch" 返回機器體系的類型.   
  5.                     # 等價於 'uname -m' ...   
  6. i386 ) echo "80386-based machine" ;;  
  7. i486 ) echo "80486-based machine" ;;  
  8. i586 ) echo "Pentium-based machine" ;;  
  9. i686 ) echo "Pentium2+-based machine" ;;  
  10. *    ) echo "Other type of machine" ;;  
  11. esac  
  12.   
  13. exit 0  



    case結構也可以過濾通配(globbing)模式的字符串.

    例子 10-27. 簡單的字符串匹配

Ruby代碼  收藏代碼
  1. #!/bin/bash   
  2. # match-string.sh: 簡單的字符串匹配   
  3.   
  4. match_string ()  
  5. {  
  6.   MATCH=0  
  7.   NOMATCH=90  
  8.   PARAMS=2     # 此函數需要2個參數.   
  9.   BAD_PARAMS=91  
  10.   
  11.   [ $# -eq $PARAMS ] || return $BAD_PARAMS   
  12.   
  13.   case  "$1"  in   
  14.   "$2"return  $MATCH ;;  
  15.   *   ) return  $NOMATCH ;;  
  16.   esac  
  17.   
  18. }    
  19.   
  20.   
  21. a=one  
  22. b=two  
  23. c=three  
  24. d=two  
  25.   
  26.   
  27. match_string $a      # 參數個數錯誤.   
  28. echo $?             # 91   
  29.   
  30. match_string $a  $b   # 不匹配   
  31. echo $?             # 90   
  32.   
  33. match_string $b  $d   # 匹配   
  34. echo $?             # 0   
  35.   
  36.   
  37. exit 0    

                 

    例子 10-28. 檢查輸入字符是否爲字母

Ruby代碼  收藏代碼
  1. #!/bin/bash   
  2. # isalpha.sh: 使用"case"結構來過濾字符串.   
  3.   
  4. SUCCESS=0  
  5. FAILURE=-1  
  6.   
  7. isalpha ()  # 檢查輸入的 *第一個字符* 是不是字母表上的字符.   
  8. {  
  9. if  [ -z "$1"  ]                # 沒有參數傳進來?   
  10. then   
  11.   return  $FAILURE   
  12. fi  
  13.   
  14. case  "$1"  in   
  15. [a-zA-Z]*) return  $SUCCESS ;;  # 以一個字母開頭?   
  16. *        ) return  $FAILURE ;;  
  17. esac  
  18. }             # 同C語言的"isalpha ()"函數比較一下.   
  19.   
  20.   
  21. isalpha2 ()   # 測試 *整個字符串* 是否都是字母表上的字符.   
  22. {  
  23.   [ $# -eq 1 ] || return $FAILURE   
  24.   
  25.   case  $1  in   
  26.   *[!a-zA-Z]*|""return  $FAILURE ;;  
  27.                *) return  $SUCCESS ;;  
  28.   esac  
  29. }  
  30.   
  31. isdigit ()    # 測試 *整個字符串* 是否都是數字.   
  32. {             # 換句話說, 就是測試一下是否是整數變量.   
  33.   [ $# -eq 1 ] || return $FAILURE   
  34.   
  35.   case  $1  in   
  36.   *[!0-9]*|""return  $FAILURE ;;  
  37.             *) return  $SUCCESS ;;  
  38.   esac  
  39. }  
  40.   
  41.   
  42.   
  43. check_var ()  # 測試isalpha().   
  44. {  
  45. if  isalpha "$@"   
  46. then   
  47.   echo "/"$*/" begins with an alpha character."   
  48.   if  isalpha2 "$@"   
  49.   then         # 不需要測試第一個字符是否是non-alpha.   
  50.     echo "/"$*/" contains only alpha characters."   
  51.   else   
  52.     echo "/"$*/" contains at least one non-alpha character."   
  53.   fi    
  54. else   
  55.   echo "/"$*/" begins with a non-alpha character."   
  56.               # 如果沒有參數傳遞進來, 也是"non-alpha".   
  57. fi  
  58.   
  59. echo  
  60.   
  61. }  
  62.   
  63. digit_check ()  # 測試isdigit().   
  64. {  
  65. if  isdigit "$@"   
  66. then   
  67.   echo "/"$*/" contains only digits [0 - 9]."   
  68. else   
  69.   echo "/"$*/" has at least one non-digit character."   
  70. fi  
  71.   
  72. echo  
  73.   
  74. }  
  75.   
  76. a=23skidoo  
  77. b=H3llo  
  78. c=-What?  
  79. d=What?  
  80. e=`echo $b `   # 命令替換.   
  81. f=AbcDef  
  82. g=27234  
  83. h=27a34  
  84. i=27.34  
  85.   
  86. check_var $a   
  87. check_var $b   
  88. check_var $c   
  89. check_var $d   
  90. check_var $e   
  91. check_var $f   
  92. check_var     # 沒有參數傳遞進來, 將會發生什麼?   
  93. #   
  94. digit_check $g   
  95. digit_check $h   
  96. digit_check $i   
  97.   
  98.   
  99. 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.   
  3. PS3='Choose your favorite vegetable: '  # 設置提示符字串.   
  4.   
  5. echo  
  6.   
  7. select vegetable in  "beans"  "carrots"  "potatoes"  "onions"  "rutabagas"   
  8. do   
  9.   echo  
  10.   echo "Your favorite veggie is $vegetable."   
  11.   echo "Yuck!"   
  12.   echo  
  13.   break   # 如果這裏沒有 'break' 會發生什麼?   
  14. done  
  15.   
  16. exit 0  



    如果忽略了in list列表, 那麼select命令將會使用傳遞到腳本的命令行參數($@), 或者是函數參數(當select是在函數中時).

    與忽略in list的

    for variable [in list]
    結構比較一下.

    例子 10-30. 使用函數中的select結構來創建菜單

Ruby代碼  收藏代碼
  1. #!/bin/bash   
  2.   
  3. PS3='Choose your favorite vegetable: '   
  4.   
  5. echo  
  6.   
  7. choice_of()  
  8. {  
  9. select vegetable  
  10. # [in list]被忽略, 所以'select'使用傳遞給函數的參數.   
  11. do   
  12.   echo  
  13.   echo "Your favorite veggie is $vegetable."   
  14.   echo "Yuck!"   
  15.   echo  
  16.   break   
  17. done  
  18. }  
  19.   
  20. choice_of beans rice carrots radishes tomatoes spinach  
  21. #         $1    $2   $3      $4       $5       $6   
  22. #         傳遞給choice_of()的參數   
  23.   
  24. exit 0 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章