1. 程式人生 > >bash腳本編程之條件判斷

bash腳本編程之條件判斷

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腳本編程之條件判斷