條件判斷:case語句
case 變量引用 in
PAT1)
分支1
;;
PAT2)
分支2
;;
...
*)
默認分支
;;
esac
示例:
#!/bin/bash # cat << EOF cpu) show cpu information; mem) show memory information; disk) show disk information; quit) quit ============================ EOF read -p "Enter a option: " option while [ "$option" != 'cpu' -a "$option" != 'mem' -a "$option" != 'disk' -a "$option" != 'quit' ]; do read -p "Wrong option, Enter again: " option done case "$option" in cpu) lscpu ;; mem) cat /proc/meminfo ;; disk) fdisk -l ;; *) echo "Quit..." exit 0 ;; esac
練習:寫一個腳本,完成如下要求
(1) 腳本可接受參數:start, stop, restart, status;
(2) 如果參數非此四者之一,提示使用格式後報錯退出;
(3) 如果是start:則創建/var/lock/subsys/SCRIPT_NAME, 並顯示“啓動成功”;
考慮:如果事先已經啓動過一次,該如何處理?
(4) 如果是stop:則刪除/var/lock/subsys/SCRIPT_NAME, 並顯示“停止完成”;
考慮:如果事先已然停止過了,該如何處理?
(5) 如果是restart,則先stop, 再start;
考慮:如果本來沒有start,如何處理?
(6) 如果是status, 則
如果/var/lock/subsys/SCRIPT_NAME文件存在,則顯示“SCRIPT_NAME is running...”;
如果/var/lock/subsys/SCRIPT_NAME文件不存在,則顯示“SCRIPT_NAME is stopped...”;
其中:SCRIPT_NAME爲當前腳本名;
總結:until, while, for, case
bash腳本編程:
while, for, case, until
bash腳本編程:
case語句:
case 變量引用 in
PAT1)
分支1
;;
PAT2)
分支2
;;
...
*)
分支n
;;
esac
case支持glob風格的通配符:
*: 任意長度任意字符;
?: 任意單個字符;
[]:指定範圍內的任意單個字符;
a|b: a或b
function:函數
過程式編程:代碼重用
模塊化編程
結構化編程
語法一:
function f_name {
...函數體...
}
語法二:
f_name() {
...函數體...
}
調用:函數只有被調用纔會執行;
調用:給定函數名
函數名出現的地方,會被自動替換爲函數代碼;
函數的生命週期:被調用時創建,返回時終止;
return命令返回自定義狀態結果;
0:成功
1-255:失敗
#!/bin/bash # function adduser { if id $username &> /dev/null; then echo "$username exists." return 1 else useradd $username [ $? -eq 0 ] && echo "Add $username finished." && return 0 fi } for i in {1..10}; do username=myuser$i adduser done
示例:服務腳本
#!/bin/bash # # chkconfig: - 88 12 # description: test service script # prog=$(basename $0) lockfile=/var/lock/subsys/$prog start() { if [ -e $lockfile ]; then echo "$prog is aleady running." return 0 else touch $lockfile [ $? -eq 0 ] && echo "Starting $prog finished." fi } stop() { if [ -e $lockfile ]; then rm -f $lockfile && echo "Stop $prog ok." else echo "$prog is stopped yet." fi } status() { if [ -e $lockfile ]; then echo "$prog is running." else echo "$prog is stopped." fi } usage() { echo "Usage: $prog {start|stop|restart|status}" } if [ $# -lt 1 ]; then usage exit 1 fi case $1 in start) start ;; stop) stop ;; restart) stop start ;; status) status ;; *) usage esac
練習:打印九九乘法表,利用函數實現;
函數返回值:
函數的執行結果返回值:
(1) 使用echo或print命令進行輸出;
(2) 函數體中調用命令的執行結果;
函數的退出狀態碼:
(1) 默認取決於函數體中執行的最後一條命令的退出狀態碼;
(2) 自定義退出狀態碼:
return
函數可以接受參數:
傳遞參數給函數:調用函數時,在函數名後面以空白分隔給定參數列表即可;例如“testfunc arg1 arg2 ...”
在函數體中當中,可使用$1, $2, ...調用這些參數;還可以使用$@, $*, $#等特殊變量;
示例:添加10個用戶
#!/bin/bash # function adduser { if [ $# -lt 1 ]; then return 2 # 2: no arguments fi if id $1 &> /dev/null; then echo "$1 exists." return 1 else useradd $1 [ $? -eq 0 ] && echo "Add $1 finished." && return 0 fi } for i in {1..10}; do adduser myuser$i done
練習:打印NN乘法表,使用函數實現;
變量作用域:
本地變量:當前shell進程;爲了執行腳本會啓動專用的shell進程;因此,本地變量的作用範圍是當前shell腳本程序文件;
局部變量:函數的生命週期;函數結束時變量被自動銷燬;
如果函數中有局部變量,其名稱同本地變量;
在函數中定義局部變量的方法:
local NAME=VALUE
函數遞歸:
函數直接或間接調用自身;
N!=N(n-1)(n-2)...1
n(n-1)! = n(n-1)(n-2)!
#!/bin/bash # fact() { if [ $1 -eq 0 -o $1 -eq 1 ]; then echo 1 else echo $[$1*$(fact $[$1-1])] fi } fact 5
練習:求n階斐波那契數列;
#!/bin/bash # fab() { if [ $1 -eq 1 ]; then echo 1 elif [ $1 -eq 2 ]; then echo 1 else echo $[$(fab $[$1-1])+$(fab $[$1-2])] fi } fab 7