1. 程式人生 > >bash程式設計之case語句,函式

bash程式設計之case語句,函式

bash指令碼程式設計:之case語句   條件測試: 0: 成功 1-255: 失敗   命令: [ expression ] [[ expression ]] test expression   exPression: 整數測試: -gt, -ge, -lt, -le, -eq, -ne 字串: >, < , >=, <=, ==, !=, =~, -z, -n 檔案: -e, -f, -d, -b, -c, -h, -S, -s, -a, -p, -r, -w, -x
  多分支的if語句: if boolean_expression1; then suite1 elif boolean_expression2; then suite2 ... elif boolean_expressionn; then suiten else else_suite fi   練習:寫一個指令碼,接受如此格式 script.sh {start|stop|restart|status} 1、如是start,那麼建立/var/lock/subsys/script.sh,顯示啟動成功; 2、如果引數是stop,則刪除/var/lock/subsys/script.sh,顯示停止成功 3、如果restart,則刪除,再建立,顯示成功; 4、如果status, 如果檔案存在,則顯示running,否則,顯示stopped   #!/bin/bash # myService=`basename $0` lockFile="/var/lock/subsys/$myService"   [ $# -lt 1 ] && echo "Usage: $myService {start|stop|restart|status}" && exit 4   if [ "$1" == 'start' ]; then         touch $lockFile         echo "Starting $myService OK" elif [ "$1" == 'stop' ]; then         rm -f $lockFile         echo "Stopping $myService OK" elif [ "$1" == 'restart' ]; then         rm -f $lockFile         touch $lockFile         echo "Restarting $myService OK" elif [ "$1" == 'status' ]; then         if [ -f $lockFile ]; then                 echo "$myService is running"         else                 echo "$myService is stopped"         fi else         echo "Usage: $myService {start|stop|restart|status}"         exit 3 fi     case語句的語法格式: case expression in pattern1) suite1 
;; pattern2) suite2 ;; ... patternn) suiten ;; *) other_suite ;; esac   上述指令碼的case實現:   #!/bin/bash # myService=`basename $0` lockFile="/var/lock/subsys/$myService"   [ $# -lt 1 ] && echo "Usage: $myService {start|stop|restart|status}" && exit 4   case $1 in 'start')         touch $lockFile         echo "Starting $myService OK"         ;; 'stop')         rm -f $lockFile         echo "Stopping $myService OK"         ;; 'restart')         rm -f $lockFile         touch $lockFile         echo "Restarting $myService OK"         ;; 'status')         if [ -f $lockFile ]; then                 echo "$myService is running"         else                 echo "$myService is stopped"         fi         ;; *)         echo "Usage: $myService {start|stop|restart|status}"         exit 3         ;; esac     case中各pattern可以使用模式: a|b: a或者b
*:匹配任意長度的任意字元; ?:匹配任意單個字元; [-]:範圍匹配   [a-z]) [0-9])   練習:寫一個簡單指令碼 1、提示使用者輸入一個任意字元; 2、能判斷此字元是數字、字母或特殊字元;   #!/bin/bash # while true; do read -p "Enter a char: " char   [[ "$char" == 'quit' ]] && break   case $char in [a-z])         echo "letter"         ;; [0-9])         echo "digit"         ;; *)         echo "special"         ;; esac done     練習:寫一個指令碼,能對/etc/目錄進行打包備份,備份位置為/backup/etc-日期.字尾 1、顯示如下選單給使用者: xz) xz compress gzip) gzip compress bip2) bzip2 compress 2、根據使用者指定的壓縮工具使用tar打包壓縮; 3、預設為xz;輸入錯誤則需要使用者重新輸入;   #!/bin/bash # [ -d /backup ] || mkdir /backup   cat << EOF Plz choose a compress tool:   xz) xz compress gzip) gzip compress bip2) bzip2 compress EOF   while true; do   read -p "Your option: " option   option=${option:-xz}     case $option in   xz)     compressTool='J'     suffix='xz'     break ;;   gzip)     compressTool='z'     suffix='gz'     break ;;   bzip2)     compressTool='j'     suffix='bz2'     break ;;   *)     echo "wrong option." ;;   esac done   tar ${compressTool}cf /backup/etc-`date +%F-%H-%M-%S`.tar.$suffix /etc/*   練習:寫一個指令碼,完成如下功能 說明:此指令碼能夠為指定網絡卡建立別名,指定地址;使用格式:mkethalias.sh -v|--verbose -i|--interface ethX 1|-i選項用於指定網絡卡; 2、如果網絡卡存在:在命令列,請使用者指定一個別名; 3、讓使用者指定IP和掩碼; 4、使用者可以同時使用-v或--verbose選項:如果使用了,則在配置完成後,顯示配置結果;否則,則不予顯示;   #!/bin/bash # debug=0   while [ $# -ge 1 ]; do   case $1 in   -i|--interface)     ethcard="$2"     shift 2 ;;   -v|--verbose)     debug=1     shift     ;;   *)     echo "Wrong options or arguments."     echo "Usage: `basename $0` [-v|--verbose] -i|--interface Interface"     shift $#     ;;   esac done   # echo "Interface: $ethcard , Verbose Flag: $debug "   ! ifconfig $ethcard &> /dev/null && echo "No this interface..." && exit 3   read -p "Enter an alias: " ethAlias   read -p "Enter IP: " ipAddr   read -p "Mask: " netMask   ifconfig $ethAlias $ipAddr netmask $netMask   [ $debug -eq 1 ] && ifconfig $ethAlias     bash指令碼程式設計之函式 模組化程式設計的工具   函式:function,功能元件   可被呼叫:函式有函式名 函數出現的地方,而自動被替換成函式定義的程式碼   函式定義     語法: FuncName() { 函式體 }   function FuncName { 函式體 }     函式有兩種返回值: 正常返回的資料: 函式中的列印語句,如echo或print 函式中命令的執行結果 執行狀態返回值: 取決於函式中執行的最後一條語句 自定義:return N   函式可以接受引數: 在函式體可以使用類似指令碼呼叫位置引數一樣的引數 $1, $2, ... $# $*, [email protected]     #!/bin/bash # function ShowUserInfo {   [ $# -lt 1 ] && return 6   grep "^$1\>" /etc/passwd | cut -d: -f3,7 }   function main { while true; do   read -p "Plz enter a user name: " userName     if [ "$userName" == 'quit' ]; then         echo "Quit"         exit 0   fi     if ! id $userName &> /dev/null; then     echo "No such user, please again."     continue   fi   ShowUserInfo $userName done }   main     練習:寫一個指令碼,完成如下功能 1、顯示如下選單 disk) show disk info mem) show memory info cpu) show cpuinfo 2、顯示使用者選定的內容;   #!/bin/bash # ShowMenu() { cat << EOF disk) show disk info mem) show memory info cpu) show cpuinfo EOF }   main() { ShowMenu read -p "Plz choose an option: " option case $option in disk)    df -h    ;; mem)    free -m    ;; cpu)   cat /proc/cpuinfo   ;; *)   echo "Wrong option" esac }   main   如果在函式中使用變數:變數作用域 在函式中使用了在主程式中宣告的變數,重新賦值會直接修改主程式中的變數; 如果不期望函式與主程式中的變數衝突,函式中使用變數都用local修飾;即使用區域性變數; 在函式中使用了在主程式中沒有宣告的變數,在函式執行結束後即被撤消,無論是否使用local修飾符;     如果想把指令碼的全部位置引數,統統傳遞給指令碼中某函式使用,怎麼辦? 使用$*傳遞           練習:寫一個指令碼,判定172.16.0.0網路內有哪些主機線上,線上的用綠色顯示,不線上的用紅色顯示;要求,程式設計中使用函式;   C類網:ping NetAdd.HostAdd B類網:ping NetAadd.NetAadd.HostAdd.HostAdd   CnetPing() { for i in {1..254}; do ping -c 1 -w 1 $1.$i }   # CnetPing 192.168.10   BnetPing() { for j in {0.255}; do CnetPing $1.$j done }   AnetPing() { for m in {0..255}; do BnetPing $1.$m done }   netType=`echo $1 | cut -d'.' -f1`   if [ $netType -gt 0 -a $netType -le 126 ]; then AnetPing $1 elif [ $netType -ge 128 -a $netType -le 191 ]; then   BnetPing $1 elif [ $netType -ge 192 -a $netType -le 223 ]; then CnetPing $1 else echo "Wrong" exit 3 fi       練習:寫一個指令碼,完成如下功能(使用函式): 1、提示使用者輸入一個可執行命令; 2、獲取這個命令所依賴的所有庫檔案(使用ldd命令); 3、複製命令至/mnt/sysroot/對應的目錄中 解釋:假設,如果複製的是cat命令,其可執行程式的路徑是/bin/cat,那麼就要將/bin/cat複製到/mnt/sysroot/bin/目錄中,如果複製的是useradd命令,而useradd的可執行檔案路徑為/usr/sbin/useradd,那麼就要將其複製到/mnt/sysroot/usr/sbin/目錄中; 4、複製各庫檔案至/mnt/sysroot/對應的目錄中,其要求命令;   #!/bin/bash # target=/mnt/sysroot   clearCmd() {   if which $cmd &> /dev/null; then         cmdPath=`which --skip-alias $cmd`   else         echo "No such command"         return 5   fi }   cmdCopy() {         cmdDir=`dirname $1`         [ -d ${target}${cmdDir} ] || mkdir -p ${target}${cmdDir}         [ -f ${target}${1} ] || cp $1 ${target}${cmdDir} }   libCopy() {         for lib in `ldd $1 | grep -o "/[^[:space:]]\{1,\}"`; do                 libDir=`dirname $lib`                 [ -d ${target}${libDir} ] || mkdir -p ${target}${libDir}                 [ -f ${target}${lib} ] || cp $lib ${target}${libDir}         done }   while true; do   read -p "Enter a command: " cmd   if [ "$cmd" == 'quit' ] ;then         echo "quit"         exit 0   fi   clearCmd $cmd   [ $? -eq 5 ] && continue     cmdCopy $cmdPath   libCopy $cmdPath done         練習:寫一個指令碼,完成如下功能(使用函式): 1、指令碼使用格式: mkscript.sh [-D|--description "script description"] [-A|--author "script author"] /path/to/somefile 2、如果檔案事先不存在,則建立;且前幾行內容如下所示: #!/bin/bash # Description: script description # Author: script author # 3、如果事先存在,但不空,且第一行不是“#!/bin/bash”,則提示錯誤並退出;如果第一行是“#!/bin/bash”,則使用vim開啟指令碼;把游標直接定位至最後一行 4、開啟指令碼後關閉時判斷指令碼是否有語法錯誤 如果有,提示輸入y繼續編輯,輸入n放棄並退出; 如果沒有,則給此檔案以執行許可權;   arguParse() {   }