簡介
在bash腳本編程中,條件結構體使用if陳述句和case陳述句兩種句式,
if陳述句
單分支if陳述句
if TEST; then CMD fi
TEST:條件判斷,多數情況下可使用test命令來實作,回傳值為0的話則執行CMD,否則就離開該條件結構體,腳本繼續往下執行,
[root@c7-server ~]# cat test.sh #!/bin/bash if id zwl &> /dev/null; then echo "User zwl exists." fi [root@c7-server ~]# bash test.sh User zwl exists.
雙分支if陳述句
if TEST; then
CMD-TRUE else
CMD-FALSE fi
為真執行CMD-TRUE,為假執行CMD-FALSE,
[root@c7-server ~]# cat test.sh #!/bin/bash read -p "Pleas input a user name:" name if id $name &> /dev/null; then echo "User $name exists." else echo "User $name doesn't exists." fi [root@c7-server ~]# bash test.sh Pleas input a user name:zwl User zwl exists. [root@c7-server ~]# bash test.sh Pleas input a user name:alongdidi User alongdidi doesn't exists.
多分支if陳述句
if TEST1; then CMD1 elif TEST2; then CMD2 elif TEST3; then CMD3 ... else CMD-LAST fi
當TEST1為真時執行CMD1,否則判斷TEST2;當TEST2為真時執行CMD2,否則判斷TEST3;以此類推,都不符合條件的話則執行CMD-LAST,
判斷檔案型別的示例,
#!/bin/bash read -p "Please input only a absolute file path:" file if [ -z $file ]; then echo "You must input something." exit 2 fi if [ ! -e $file ]; then echo "No such file $file" elif [ -d $file ]; then echo "File $file is a directory." elif [ -L $file ]; then echo "File $file is a symbolic." elif [ -b $file ]; then echo "File $file is a block special file." elif [ -c $file ]; then echo "File $file is a character special file." elif [ -S $file ]; then echo "File $file is a socket file." elif [ -f $file ]; then echo "File $file is a regular file." else echo "File is unrecognized." fi
執行示例,
[root@c7-server ~]# bash test.sh Please input only a absolute file path: You must input something. [root@c7-server ~]# bash test.sh Please input only a absolute file path:passwd No such file passwd [root@c7-server ~]# bash test.sh Please input only a absolute file path:/etc/passwd File /etc/passwd is a regular file [root@c7-server ~]# bash test.sh Please input only a absolute file path:/root/ File /root/ is a directory. [root@c7-server ~]# bash test.sh Please input only a absolute file path:/etc/rc.local File /etc/rc.local is a symbolic.
字符鏈接檔案也可以被認為是普通檔案(regular),因此建議將普通檔案的判定放置在較靠后的位置,
注意:if陳述句是可以嵌套的,
[root@c7-server ~]# cat test.sh #!/bin/bash if [ -e /dev/sda ]; then if [ -b /dev/sda ]; then echo "It's a block file." fi fi [root@c7-server ~]# bash test.sh It's a block file.
其他示例
撰寫一個腳本,僅可接收一個引數,此引數應是一個用戶名稱,判斷該用戶名是否存在,若存在則輸出用戶的資訊,否則就創建該用戶并設定默認密碼(password),
#!/bin/bash if [ $# -ne 1 ];then echo "You must input just one argument!" exit 2 fi if id $1 &> /dev/null; then id $1 else useradd $1 echo "password" | passwd --stdin $1 &> /dev/null fi
撰寫一個腳本,接收兩個數值類引數,并輸出其中較大的那個,
#!/bin/bash if [ $# -ne 2 ]; then echo "Please input exact two number arguments." exit 1 fi if [ $1 -eq $2 ]; then echo "Number $1 and $2 are equal." elif [ $1 -gt $2 ]; then echo "The greater is $1." else echo "The greater is $2." fi
撰寫一個腳本,接收一個用戶名作為引數,并判斷其奇偶性,
[root@c7-server ~]# cat even_odd_if.sh #!/bin/bash if [ $# -ne 1 ]; then echo "You must input just one argument." exit 1 fi var=$[$(id -u $1)%2] if [ $var -eq 0 ]; then echo "The UID of $1 is even." else echo "The UID of $1 is odd." fi
撰寫一個腳本,接收兩個檔案名作為引數,回傳檔案的行數以及判斷哪個檔案的行數比較多,
#!/bin/bash if [ $# -ne 2 ]; then echo "You must input exat 2 arguments." exit 1 fi if [ ! -e $1 -o ! -e $2 ]; then echo "File $1 or/and $2 doesn't/don't exist[s]." exit 2 fi line1=$(wc -l $1 | cut -d " " -f 1) line2=$(wc -l $2 | cut -d " " -f 1) echo "The lines of $1 is $line1" echo "The lines of $2 is $line2" if [ $line1 -gt $line2 ]; then echo "$1 has more lines." elif [ $line1 -lt $line2 ]; then echo "$2 has more lines." else echo "They have same lines." fi
撰寫一個腳本,傳遞一個用戶名作為引數給腳本,判斷用戶的型別,
UID=0:管理員
UID=1~999:系統用戶
UID=1000+:普通用戶
#!/bin/bash if [ $# -ne 1 ]; then echo "You must input exact one argument." exit 1 fi if ! id $1 &> /dev/null; then echo "You must input an existed username." exit 2 fi userId=$(id -u $1) if [ $userId -eq 0 ]; then echo "$1 is a admin user." elif [ $userId -lt 1000 ]; then echo "$1 is a system user." else echo "$1 is a normal user." fi
撰寫一個腳本,展示一個選單供用戶選擇,選單告知用戶腳本可以顯示的系統資訊,
#!/bin/bash cat << EOF disk) Show disk infomation. mem) Show memory infomation. cpu) Show cpu infomation. *) QUIT! EOF read -p "Your option is: " option if [ -z $option ]; then echo "You input nothing,QUIT!" exit 1 elif [ $option == disk ]; then fdisk -l elif [ $option == mem ]; then free -m elif [ $option == cpu ]; then lscpu else echo "You input a illegal string,QUIT now!" fi
在后面學習了回圈之后,可以加上回圈,使得用戶在輸入錯誤的情況下,反復讓用戶輸入直到輸入正確的選項,
#!/bin/bash cat << EOF disk) Show disk infomation. mem) Show memory infomation. cpu) Show cpu infomation. *) Again! EOF read -p "Your option is: " option while [ "$option" != disk -a "$option" != mem -a "$option" != cpu -o "$option" == "" ]; do echo "You input a illegal string. Usage {disk|mem|cpu}, case sensitive." read -p "Your option is: " option done if [ $option == disk ]; then fdisk -l elif [ $option == mem ]; then free -m elif [ $option == cpu ]; then lscpu fi
這個腳本的難點我覺得在于while回圈中的判斷應該怎么寫,$option是否應該加引號、字串匹配右邊的字符(如disk)是否需要加引號、使用單中括號還是雙中括號、使用單引號還是雙引號,我也是一遍遍試直到瞎貓碰到死耗子才寫出來符合自己需求的bash代碼,
具體涉及的難點包括但《Bash腳本編程學習筆記04:測驗命令test、狀態回傳值、位置引數和特殊變數》文章開頭說的那些,因此這里無法為大家做到準確的分析,
case陳述句
像上述腳本中,我們反復對一個變數做字串等值比較并使用了多分支的if陳述句,此類情況我們完全可以使用case陳述句來代替,使其更容易看懂,
其官方語法如下:
case word in [ [(] pattern [| pattern]…) command-list ;;]… esac
case會將word和pattern進行匹配,一旦匹配到就執行對應的command-list,并且退出,
pattern基于bash的模式匹配,即glob風格,
pattern至少一個,可以有多個使用“|”分隔,
pattern+command-list成為一個子句(clause),如下,
[(] pattern [| pattern]…) command-list ;;
每個子句,都會以“;;”或者“;&”或者“;;&”結束,基本上只會使用“;;”,
;;:決定了一旦word第一次匹配到了pattern,就執行對應的command-list,并且退出,
;&和;;&:而這兩個是不會在第一次匹配到就立刻退出的,還會有其他后續的動作,幾乎很少用到,有需要的可以去看手冊,
word在匹配前會經歷:波浪符展開、引數展開、命令替換、算術展開和引號去除,
pattern會經歷:波浪符展開、引數展開、命令替換和算術展開,
當word的值是一個通配符的時候,表示默認的case,類似多分支if陳述句最后的else,
來個官方示例,簡單易懂,
#!/bin/bash echo -n "Enter the name of an animal: " read ANIMAL echo -n "The $ANIMAL has " case $ANIMAL in horse | dog | cat) echo -n "four";; man | kangaroo ) echo -n "two";; *) echo -n "an unknown number of";; esac echo " legs."
學會了case陳述句后,我們就可以對上面的多分支if陳述句的最后一個示例(顯示系統資訊的)進行改寫,改為case陳述句的,應該不難,這里不演示了,我們嘗試新的腳本,
我們嘗試寫一個bash服務類腳本,常見于CentOS 6系列的系統中的/etc/rc.d/init.d/目錄下,
- 腳本的名稱一般就是服務名稱,不會帶“.sh”,
- 服務腳本一般會創建一個空檔案作為鎖檔案,若此檔案存在則表示服務處于運行狀態;反之,則服務處于停止狀態,
- 腳本只能接收四種引數:start, stop, restart, status,
- 我們并不會真正啟動某行程,只要echo即可,啟動時需創建鎖檔案,停止時需洗掉鎖檔案,
- 適當加入條件判斷使得腳本更健壯,
#!/bin/bash # # chkconfig: - 50 50 # Description: test service script # prog=$(basename $0) lockfile="/var/lock/subsys/$prog" case $1 in start) if [ -e $lockfile ]; then echo "The service $prog has already started." else touch $lockfile echo "The service $prog starts finished." fi ;; stop) if [ ! -e $lockfile ]; then echo "The service $prog has already stopped." else rm -f $lockfile echo "The service $prog stops finished." fi ;; restart) if [ -e $lockfile ]; then rm -f $lockfile touch $lockfile echo "The service $prog restart finished." else touch $lockfile echo "The service $prog starts finished." fi ;; status) if [ -e $lockfile ]; then echo "The service $prog is running." else echo "The service $prog is not running." fi ;; *) echo "Usage: $prog {start|stop|restart|status}" exit 1 ;; esac
腳本撰寫完成后,要放入服務腳本所在的目錄、給予權限、加入服務管控(chkconfig),最后就可以使用service命令進行測驗了,
~]# cp -av case_service.sh /etc/rc.d/init.d/case_service ‘case_service.sh’ -> ‘/etc/rc.d/init.d/case_service’ ~]# chmod a+x /etc/rc.d/init.d/case_service ~]# chkconfig --add case_service ~]# chkconfig case_service on
像這個服務類的腳本,我們在重啟時,可能執行先停止后啟動,也可能執行啟動,這些在啟動和停止時都有已經寫好的代碼了,如果可以將代碼進行重用的話,就可以減少很多代碼勞動,這就是之后要介紹的函式,
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/141620.html
標籤:Linux
