bash腳本編程之條件判斷
1、bash腳本編程格式:
頂格寫#!/bin/bash
接下來給出一些註釋信息,以#開頭如:
#description
#version
#auhor ceshi <[email protected]>
#date 2017-11-07
然後代碼註釋
縮進,適度添加空白行
2、變量介紹:
局部變量
本地變量
環境變量
位置參數變量
特殊變量
3、數據類型:
字符型
數值型
4、bash算數運算:
方法①:let var=$num1 op $num2
方法②:var=$[ expression ]
方法③:var=$((expression))
方法④:var=$(expr argu1 op argu2 )
需要註意的是:
var=變量值 //這是變量賦值
var=$(命令) //這是命令結果引用
有些時候,乘法符號(*)需要轉義實現;
5、增強型賦值:在shell腳本中要用let描述
變量做某種算數運算後回存至此變量中:
let i=$i+# //#是數字
let i+=#
此類操作符有:+=、-+、*=、/=,%=
自增:
let var+=1
let var++ //如果每次加“1”,可以寫成此種方式
自減:
let var-=1
let var-- //如果每次減“1”,可以寫成此種方式
6、練習題:
計算/etc/passwd文件中的第10個用戶和第20個用戶的uid之和
id1=$(head -10 /etc/passwd | tail -1 | cut -d: -f3)
id2=$(head -20 /etc/passwd | tail -1 | cut -d: -f3)
idsum=$[ $id1 + $id2]
7、shell腳本編程之條件測試(測試表達式)
判斷某需求是否滿足;需要由測試機制來實現。
如何編寫測試表達式以實現所需要的測試:
如#grep "^$" /etc/rc.d/init.d/functions &> /dev/null
#echo $?
①、有專門命令實現測試表達式,使用執行命令,並利用命令狀態返回值來判斷:
0:成功
1-255:失敗
如:查看centos用戶是否登陸系統:
#w | grep "^centos\>"
#echo $?
②、沒有專門命令實現,這類需要用到測試表達式(如:大小、長短等)
方法一:test expression
方法二:[ expression ] //註意:expression兩端必須有空白字符,否則為語法錯誤
方法三:[[ expression ]] //註意:expression兩端必須有空白字符,否則為語法錯誤
8、bash的測試表達式類型:
數值測試
字符串測試
文件測試
8.1、數值測試:用於實現數值大小比較:
-eq :是否等於;如[ $num1 -eq $num2 ]
-ne :是否不等於
-gt :是否大於
-ge :是否大於等於
-lt :是否小於
-le :是否小於等於
8.2、字符串測試:字符比較;比較時,變量要加引號
== :是否等於 如:[ "tom" =="tmo" ]
> :是否大於
< :是否小於
!= :是否不等於
=~:左側字符串是否能夠被右側的PATTERN所匹配;可以匹配左側字符串的部分內容。
-z "string":判斷指定的字串“string”是否為空,空則為真,不空為假
-n "string":判斷指定的字串"string" 是否為不空,不空為真,空則為假。
註意1:做字符串測試時,要在[[ expression ]]兩個中括號中做比較,一個中括號有時是不生效的。
如:#[[ a>b ]]
#echo $?
註意2:字符串要加引號,表示引用,做變量引用時不能用單引號。
8.3、文件測試:
存在性測試:文件的存在性測試,存在為真,不存在為假
-a FILE
-e FILE
文件存在性及類型測試:
-b FILE :是否存在並且為塊設備文件
-c FILE :是否存在並且為字符設備文件
-d FILE :是否存在並且為目錄文件
-f FILE :是否存在並且為普通文件
-h FILE :是否存在並且為符號鏈接文件
-L FILE :是否存在並且為符號鏈接文件,大寫"L"。
-p FILE :是否存在並且為命名管道文件
-S FILE :是否存在並且為套接字文件,大寫"S"。
文件存在性及權限測試:
-r FILE :是否存在並且對當前用戶可讀
-w FILE :是否存在並且對當前用戶可寫
-x FILE :是否存在並且對當前用戶可執行。
文件存在性及特殊權限測試:
-g FILE :是否存在並且擁有sgid權限
-u FILE :是否存在並且擁有suid權限
-k FILE :是否存在並且擁有sticky權限
文件存在性及大小測試:文件是否有內容
-s FILE :是否存在並且有內容,有為真沒有為假;小寫“s”
文件存在性及時間戳測試:
-N FILE :文件自從上一次讀操作後是否被修改過。
文件存在性及從屬關系測試
-O FILE :文件是否存在並且當前用戶是文件屬主。
-G FILE :文件是否存在並且當前用戶屬於文件屬組。
雙目測試:
FILE1 -eq FILE2 :FILE1與FILE2是否為指向同一文件系統的相同inode的硬鏈接
FILE1 -N FILE2 :FILE1是否新於FILE2
8.4、組合測試條件:
邏輯運算:
方法一:
command1 && command2
command1 || command2
! command2
方法二:
test EXPRESSION1 -a|-o|!EXPRESSION2
方法三:[ EXPRESSION1 -a|-o|!EXPRESSION2 ]
方法四:[[ EXPRESSION1 -a|-o|!EXPRESSION2 ]]
如:
[ -o FILE -a -x FILE ] //表示測試用戶是否屬於當前用戶並有執行權限。
9、腳本的狀態返回值:
默認是腳本中執行的最後一條命令的狀態返回值,可以自定義狀態退出狀態碼,如下:
exit [n] :n為自己指定的狀態碼;若不指定n,默認0為真,其他為假,
註意:shell進程遇到exit時,即會終止,因此整個腳本執行即為結束。
如:id user3 &> /dev/null && exit 0 || useradd user3
練習1:將當前主機名稱保存至hostname變量中;主機名如果為空,或者為localhost.localdomain,則將其設置為www.magedu.com
[root@localhost ~]# hostname=$(hostname)
[root@localhost ~]# [ -z "$hostname" -o "$hostname" == "localhost.localdomain" ] && hostname www.magedu.com
10、位置參數變量:向腳本傳遞參數
位置參數變量格式:
MYSCRIPT ARGU1 ARGU2 //腳本 參數1 參數2
位置參數變量應用方式:$1,$2,.....${10},${...},
如:
有一個腳本如下:
#!/bin/bash
echo "put two arg"
let sum=$1+$2
echo $sum
運行:
[root@localhost ~]# bash ./script 2 3 //其中2 3 為位置參數表示腳本中的$1,$2
put two arg
5
[root@localhost ~]#
位置參數輪替:
格式:shift [n] //一次將n個參數踢出,可以不加n,表示默認一個
如:
#!/bin/bash
echo " firsh pos argus :$1,$3"
shift 2
echo "second pos argus :$1"
運行:
~]# bash ./shift.sh 1 2 3 //一次踢出兩個參數,那個再一次給$1賦值 即是第三個數
firsh pos argus :1,3
second pos argus :3
[root@localhost ~]#
練習:
寫一個腳本,通過命令傳遞兩個文本文件路徑給腳本,計算空白行數之和
1 #!/bin/bash
2 lin1=$(grep "^$" "$1"| wc -l)
3 lin2=$(grep "^$" "$2"| wc -l)
4 echo $[$lin1+$lin2]
運行:
[root@localhost ~]# bash ./line0.sh /etc/fstab /etc/issue
2
[root@localhost ~]#
11、特殊變量
$0:腳本文件路徑本身
$#:腳本參數的個數
$*:所有參數,把所有參數當作一個個單獨的字符串
$@:所有參數,把所有參數當作一個個字符串來看待
引用9:
腳本的狀態返回值:
默認是腳本中執行的最後一條命令的狀態返回值,可以自定義狀態退出狀態碼,如下:
exit [n] :n為自己指定的狀態碼,0為真,其他為假
註意:shell進程遇到exit時,即會終止,因此整個腳本執行即為結束。
如:id user3 &> /dev/null && exit 0 || useradd user3
如下腳本:
1 #!/bin/bash
2 [ $# -lt 2 ] && echo "input two argu" && exit 10
3
4 lin1=$(grep "^$" "$1"| wc -l)
5 lin2=$(grep "^$" "$2"| wc -l)
6 echo $[$lin1+$lin2]
運行:
[root@localhost ~]# bash ./line0.sh /etc/fstab
input two argu
[root@localhost ~]# echo $? //查看執行狀態,由於有exit命令,因此不會執行到最後一條語句
10
[root@localhost ~]#
12、過程式編程語言的代碼執行順序: 順序執行:逐條運行 選擇執行:代碼有一個或多個 代碼有一個分支:條件滿足時才會運行 代碼有兩個或以上分支:只會執行其中一個滿足條件的分支 循環執行: 代碼片段(即循環體)要執行0次,1次,或多次的循環。 | |
12.1、選擇執行--單分支的if語句 格式一: if 測試條件 then 代碼分支 fi 格式二: if 測試條件;then 代碼分支 fi | 12.2、選擇執行--雙分支的if語句 格式: if 測試條件;then 條件為真時執行的分支 else 條件為假時執行的分支 fi |
選擇執行示例一: 通過參數傳遞一個用戶名給腳本,此用戶不存在時,則添加此用戶: 腳本如下: #!/bin/bash if ! grep "^$1\> " /etc/passwd &> /dev/null ;then useradd "$1" echo $1 | passwd --stdin $1 &> /dev/null fi 運行腳本如下: [root@localhost ~]# grep "^zhang\>" /etc/passwd [root@localhost ~]# bash ./user.sh zhang [root@localhost ~]# grep "^zhang\>" /etc/passwd zhang:x:2013:2013::/home/zhang:/bin/bash [root@localhost ~]# | |
選擇執行示例二: 通過參數傳遞一個用戶名給腳本,此用戶不存在時,則添加此用戶: 腳本如下: #!/bin/bash if [ $# -lt 1 ];then echo "input username" exit 22 fi if grep "^$1\> " /etc/passwd &> /dev/null ;then echo "$1 is exists" fi if ! grep "^$1\> " /etc/passwd &> /dev/null ;then useradd "$1" echo $1 | passwd --stdin $1 &> /dev/null fi exit 222 註意:此shell腳本中有兩處exit命令,去掉exit 22,會執行exit 222,用echo $?可以驗證,如果在之間有exit 22,則以後的語句就不會再執行了。 | |
選擇執行示例三: 通過鍵盤給定的兩個數字,輸出其中較大的值 #!/bin/bash if [ "$1" -gt "$2" ] then echo " the max is $1" else echo "the max is $2" fi 運行如下: [root@localhost ~]# bash ./max.sh 3 20 the max is 20 [root@localhost ~]# | 示例四, 求兩數較大值。 1 #!/bin/bash 2 max=$2 3 if [ "$1" -gt "$2" ] 4 then 5 max=$1 6 else 7 max=$2 8 fi 9 echo "max is $max" 註意:此處事先申明的max=$2有沒有都可以, |
選擇執行示例四: 判斷從鍵盤給定的一個用戶名,他的id是偶數還是奇數。 #!/bin/bash if [ $# -lt 1 ] ;then echo " input at least one argu:" exit 10 fi if grep "^$1\>" /etc/passwd &>/dev/null;then echo "the user:$1 is cunzai" else echo "the user:$1 is not cunzai" exit 100 fi id=$(grep "^$1\>" /etc/passwd | cut -d: -f3 ) echo $id if [ $[$id%2] -eq 0 ];then //判斷取余運算 echo $1 is ou shu else echo $1 is ji shu fi 運行如下: [root@localhost ~]# bash ./jiou.sh lucy the user:lucy is cunzai 2008 lucy is ou shu [root@localhost ~]# bash ./jiou.sh lily the user:lily is cunzai 2009 lily is ji shu [root@localhost ~]# | |
選擇執行示例五: 通過命令行參數給定兩個文件名,如果某文件不存在,則結束腳本執行;如果都存在,則返回每個文件的行數,並說明其中行數較多的文件。 #!/bin/bash echo "input two filename:$1,$2" if [ $# -lt 2 ] ;then echo "the filename_num need two" fi if [ -e "$1" -a -e "$2" ];then echo $(wc -l "$1") echo $(wc -l "$2") else echo at least one is not exists exit 20 fi line1=$(wc -l "$1" | cut -d ‘ ‘ -f1) line2=$(wc -l "$2" | cut -d ‘ ‘ -f1)
if [ "$line1" -gt "$line2" ]; then echo "the filename is $1" else echo "the filename is $2" fi 運行如下: [root@localhost ~]# bash hangshu /etc/fstab /etc/issue input two filename:/etc/fstab,/etc/issue 12 /etc/fstab 3 /etc/issue the filename is /etc/fstab |
註意:有時候腳本在編寫的時候會有錯誤,可以用bash -x來執行檢查
"-x"選項可用來跟蹤腳本的執行,是調試shell腳本的強有力工具。“-x”選項使shell在執行腳本的過程中把它實際執行的每一個命令行顯示出來,並且在行首顯示一個"+"號。 "+"號後面顯示的是經過了變量替換之後的命令行的內容,有助於分析實際執行的是什麽命令。 “-x”選項使用起來簡單方便,可以輕松對付大多數的shell調試任務,應把其當作首選的調試手段。
bash腳本編程之條件判斷