03_SHELL編程之條件判斷和流程控制

本節(jié)課程目標(biāo)

  • 熟悉條件判斷語句,如判斷整數(shù)、判斷字符串等
  • 熟悉流程控制語句基本語法,如if…else…

一、條件判斷語法結(jié)構(gòu)

思考:何為真(==true==)?何為假(==false==)?

1. ==條件判斷語法格式==

  • 格式1: ==test== 條件表達(dá)式
  • 格式2: [ 條件表達(dá)式 ]
  • 格式3: [[ 條件表達(dá)式 ]] 支持正則 =~

特別說明:

1)==[== 親親,我兩邊都有空格,不空打死你呦 ==]== :imp:

2)==[[== 親親,我兩邊都有空格,不空打死你呦 ==]]==:imp:

  1. 更多判斷,man test去查看,很多的參數(shù)都用來進(jìn)行條件判斷

2. 條件判斷相關(guān)參數(shù)

問:你要判斷什么?

答:我要判斷文件類型,判斷文件新舊,判斷字符串是否相等,判斷權(quán)限等等...

㈠ ==判斷文件類型==

判斷參數(shù) 含義
==-e== 判斷文件是否存在(任何類型文件)
-f 判斷文件是否存在==并且==是一個普通文件
-d 判斷文件是否存在并且是一個目錄
-L 判斷文件是否存在并且是一個軟連接文件
-b 判斷文件是否存在并且是一個塊設(shè)備文件
-S 判斷文件是否存在并且是一個套接字文件
-c 判斷文件是否存在并且是一個字符設(shè)備文件
-p 判斷文件是否存在并且是一個命名管道文件
==-s== 判斷文件是否存在并且是一個非空文件(有內(nèi)容)

舉例說明:

test -e file                    只要文件存在條件為真
[ -d /shell01/dir1 ]            判斷目錄是否存在,存在條件為真
[ ! -d /shell01/dir1 ]      判斷目錄是否存在,不存在條件為真
[[ -f /shell01/1.sh ]]      判斷文件是否存在,并且是一個普通的文件

㈡ 判斷文件權(quán)限

判斷參數(shù) 含義
-r 當(dāng)前用戶對其是否可讀
-w 當(dāng)前用戶對其是否可寫
-x 當(dāng)前用戶對其是否可執(zhí)行
-u 是否有suid,高級權(quán)限冒險位
-g 是否sgid,高級權(quán)限強制位
-k 是否有t位,高級權(quán)限粘滯位

㈢ 判斷文件新舊

說明:這里的新舊指的是==文件的修改時間==。

判斷參數(shù) 含義
file1 -nt file2 比較file1是否比file2新
file1 -ot file2 比較file1是否比file2舊
file1 -ef file2 比較是否為同一個文件,或者用于判斷硬連接,是否指向同一個inode

㈣ 判斷整數(shù)

判斷參數(shù) 含義
-eq 相等
-ne 不等
-gt 大于
-lt 小于
-ge 大于等于
-le 小于等于

㈤ ==判斷字符串==

判斷參數(shù) 含義
-z 判斷是否為==空==字符串,字符串長度為0則成立
-n 判斷是否為==非空==字符串,字符串長度不為0則成立
string1 = string2 判斷字符串是否相等
string1 != string2 判斷字符串是否相不等

㈥ ==多重條件判斷==

判斷符號 含義 舉例
-a 和 && 邏輯與 [ 1 -eq 1 -a 1 -ne 0 ] [ 1 -eq 1 ] && [ 1 -ne 0 ]
-o 和 || 邏輯或 [ 1 -eq 1 -o 1 -ne 1 ]

==特別說明:==

&& 前面的表達(dá)式==為真==,才會執(zhí)行后面的代碼

|| 前面的表達(dá)式==為假==,才會執(zhí)行后面的代碼

; ==只==用于==分割==命令或表達(dá)式

① 舉例說明

  • 數(shù)值比較
[root@server ~]# [ $(id -u) -eq 0 ] && echo "the user is admin"
[root@server ~]$ [ $(id -u) -ne 0 ] && echo "the user is not admin"
[root@server ~]$ [ $(id -u) -eq 0 ] && echo "the user is admin" || echo "the user is not admin"

[root@server ~]# uid=`id -u`
[root@server ~]# test $uid -eq 0 && echo this is admin
this is admin
[root@server ~]# [ $(id -u) -ne 0 ]  || echo this is admin
this is admin
[root@server ~]# [ $(id -u) -eq 0 ]  && echo this is admin || echo this is not admin
this is admin
[root@server ~]# su - stu1
[stu1@server ~]$ [ $(id -u) -eq 0 ]  && echo this is admin || echo this is not admin
this is not admin
  • 類C風(fēng)格的數(shù)值比較
注意:在(( ))中,=表示賦值;==表示判斷
[root@server ~]# ((1==2));echo $?
[root@server ~]# ((1<2));echo $?
[root@server ~]# ((2>=1));echo $?
[root@server ~]# ((2!=1));echo $?
[root@server ~]# ((`id -u`==0));echo $?
 
[root@server ~]# ((a=123));echo $a
[root@server ~]# unset a
[root@server ~]# ((a==123));echo $?
  • 字符串比較
注意:雙引號引起來,看作一個整體;= 和 == 在 [ 字符串 ] 比較中都表示判斷
[root@server ~]# a='hello world';b=world
[root@server ~]# [ $a = $b ];echo $?
[root@server ~]# [ "$a" = "$b" ];echo $?
[root@server ~]# [ "$a" != "$b" ];echo $?
[root@server ~]# [ "$a" !== "$b" ];echo $?        錯誤
[root@server ~]# [ "$a" == "$b" ];echo $?
[root@server ~]# test "$a" != "$b";echo $?


test  表達(dá)式
[ 表達(dá)式 ]
[[ 表達(dá)式 ]]

思考:[ ] 和 [[ ]] 有什么區(qū)別?

[root@server ~]# a=
[root@server ~]# test -z $a;echo $?
[root@server ~]# a=hello
[root@server ~]# test -z $a;echo $?
[root@server ~]# test -n $a;echo $?
[root@server ~]# test -n "$a";echo $?

# [ '' = $a ];echo $?
-bash: [: : unary operator expected
2
# [[ '' = $a ]];echo $?
0


[root@server ~]# [ 1 -eq 0 -a 1 -ne 0 ];echo $?
[root@server ~]# [ 1 -eq 0 && 1 -ne 0 ];echo $?
[root@server ~]# [[ 1 -eq 0 && 1 -ne 0 ]];echo $?

② 邏輯運算符總結(jié)

  1. 符號;和&&和||都可以用來分割命令或者表達(dá)式
  2. 分號(;)完全不考慮前面的語句是否正確執(zhí)行,都會執(zhí)行;號后面的內(nèi)容
  3. &&符號,需要考慮&&前面的語句的正確性,前面語句正確執(zhí)行才會執(zhí)行&&后的內(nèi)容;反之亦然
  4. ||符號,需要考慮||前面的語句的非正確性,前面語句執(zhí)行錯誤才會執(zhí)行||后內(nèi)容;反之亦然
  5. 如果&&和||一起出現(xiàn),從左往右依次看,按照以上原則

二、流程控制語句

關(guān)鍵詞:==選擇==(人生漫漫長路,我該何去何從:vertical_traffic_light:)

1. 基本語法結(jié)構(gòu)

㈠ ==if結(jié)構(gòu)==

箴言1:只要正確,就要一直向前沖:v:

==F==:表示false,為假

==T==:表示true,為真

if [ condition ];then
        command
        command
fi

if test 條件;then
    命令
fi

if [[ 條件 ]];then
    命令
fi

[ 條件 ] && command
流程判斷1.png

㈡ ==if...else結(jié)構(gòu)==

箴言2:分叉路口,二選一

if [ condition ];then
        command1
    else
        command2
fi

[ 條件 ] && command1 || command2
流程判斷2.png

小試牛刀:

==讓用戶自己輸入==字符串,==如果==用戶輸入的是hello,請打印world,==否則==打印“請輸入hello”

  1. read定義變量
  2. if....else...
#!/bin/env bash

read -p '請輸入一個字符串:' str
if [ "$str" = 'hello' ];then
    echo 'world'
 else
    echo '請輸入hello!'
fi

  1 #!/bin/env bash
  2
  3 read -p "請輸入一個字符串:" str
  4 if [ "$str" = "hello" ]
  5 then
  6     echo world
  7 else
  8     echo "請輸入hello!"
  9 fi
  
  echo "該腳本需要傳遞參數(shù)"
  1 if [ $1 = hello ];then
  2         echo "hello"
  3 else
  4         echo "請輸入hello"
  5 fi

#!/bin/env bash

A=hello
B=world
C=hello

if [ "$1" = "$A" ];then
        echo "$B"
    else
        echo "$C"
fi


read -p '請輸入一個字符串:' str;
 [ "$str" = 'hello' ] && echo 'world' ||  echo '請輸入hello!'

㈢ ==if...elif...else結(jié)構(gòu)==

箴言3:選擇很多,能走的只有一條

if [ condition1 ];then
        command1    結(jié)束
    elif [ condition2 ];then
        command2    結(jié)束
    else
        command3
fi
注釋:
如果條件1滿足,執(zhí)行命令1后結(jié)束;如果條件1不滿足,再看條件2,如果條件2滿足執(zhí)行命令2后結(jié)束;如果條件1和條件2都不滿足執(zhí)行命令3結(jié)束.
流程判斷3.png

㈣ 層層嵌套結(jié)構(gòu)

箴言4:多次判斷,帶你走出人生迷霧。

if [ condition1 ];then
        command1        
        if [ condition2 ];then
            command2
        fi
 else
        if [ condition3 ];then
            command3
        elif [ condition4 ];then
            command4
        else
            command5
        fi
fi
注釋:
如果條件1滿足,執(zhí)行命令1;如果條件2也滿足執(zhí)行命令2,如果不滿足就只執(zhí)行命令1結(jié)束;
如果條件1不滿足,不看條件2;直接看條件3,如果條件3滿足執(zhí)行命令3;如果不滿足則看條件4,如果條件4滿足執(zhí)行命令4;否則執(zhí)行命令5
流程判斷4.png

2. 應(yīng)用案例

㈠ 判斷兩臺主機(jī)是否ping通

需求:判斷==當(dāng)前主機(jī)==是否和==遠(yuǎn)程主機(jī)==是否ping通

① 思路

  1. 使用哪個命令實現(xiàn) ping -c次數(shù)
  2. 根據(jù)命令的==執(zhí)行結(jié)果狀態(tài)==來判斷是否通$?
  3. 根據(jù)邏輯和語法結(jié)構(gòu)來編寫腳本(條件判斷或者流程控制)

② 落地實現(xiàn)

#!/bin/env bash
# 該腳本用于判斷當(dāng)前主機(jī)是否和遠(yuǎn)程指定主機(jī)互通

# 交互式定義變量,讓用戶自己決定ping哪個主機(jī)
read -p "請輸入你要ping的主機(jī)的IP:" ip

# 使用ping程序判斷主機(jī)是否互通
ping -c1 $ip &>/dev/null

if [ $? -eq 0 ];then
    echo "當(dāng)前主機(jī)和遠(yuǎn)程主機(jī)$ip是互通的"
 else
    echo "當(dāng)前主機(jī)和遠(yuǎn)程主機(jī)$ip不通的"
fi

邏輯運算符
test $? -eq 0 &&  echo "當(dāng)前主機(jī)和遠(yuǎn)程主機(jī)$ip是互通的" || echo "當(dāng)前主機(jī)和遠(yuǎn)程主機(jī)$ip不通的"

㈡ 判斷一個進(jìn)程是否存在

需求:判斷web服務(wù)器中httpd進(jìn)程是否存在

① 思路

  1. 查看進(jìn)程的相關(guān)命令 ps pgrep
  2. 根據(jù)命令的返回狀態(tài)值來判斷進(jìn)程是否存在
  3. 根據(jù)邏輯用腳本語言實現(xiàn)

② 落地實現(xiàn)

#!/bin/env bash
# 判斷一個程序(httpd)的進(jìn)程是否存在
pgrep httpd &>/dev/null
if [ $? -ne 0 ];then
    echo "當(dāng)前httpd進(jìn)程不存在"
else
    echo "當(dāng)前httpd進(jìn)程存在"
fi

或者
test $? -eq 0 && echo "當(dāng)前httpd進(jìn)程存在" || echo "當(dāng)前httpd進(jìn)程不存在"

③ 補充命令

pgrep命令:以名稱為依據(jù)從運行進(jìn)程隊列中查找進(jìn)程,并顯示查找到的進(jìn)程id
選項
-o:僅顯示找到的最?。ㄆ鹗迹┻M(jìn)程號;
-n:僅顯示找到的最大(結(jié)束)進(jìn)程號;
-l:顯示進(jìn)程名稱;
-P:指定父進(jìn)程號;pgrep -p 4764  查看父進(jìn)程下的子進(jìn)程id
-g:指定進(jìn)程組;
-t:指定開啟進(jìn)程的終端;
-u:指定進(jìn)程的有效用戶ID。

㈢ 判斷一個服務(wù)是否正常

需求:判斷門戶網(wǎng)站是否能夠正常訪問

① 思路

  1. 可以判斷進(jìn)程是否存在,用/etc/init.d/httpd status判斷狀態(tài)等方法
  2. 最好的方法是==直接去訪問==一下,通過訪問成功和失敗的返回值來判斷
    • Linux環(huán)境,==wget== curl elinks -dump

② 落地實現(xiàn)

#!/bin/env bash
# 判斷門戶網(wǎng)站是否能夠正常提供服務(wù)

#定義變量
web_server=www.itcast.cn
#訪問網(wǎng)站
wget -P /shell/ $web_server &>/dev/null
[ $? -eq 0 ] && echo "當(dāng)前網(wǎng)站服務(wù)是ok" && rm -f /shell/index.* || echo "當(dāng)前網(wǎng)站服務(wù)不ok,請立刻處理"

3. 課堂練習(xí)

㈠ 判斷用戶是否存在

需求1:輸入一個用戶,用腳本判斷該用戶是否存在

 #!/bin/env bash
  2 read -p "請輸入一個用戶名:" user_name
  3 id $user_name &>/dev/null
  4 if [ $? -eq 0 ];then
  6     echo "該用戶存在!"
  7 else
  8     echo "用戶不存在!"
  9 fi
  
  
#!/bin/bash
# 判斷 用戶(id) 是否存在
read -p "輸入壹個用戶:" id
id $id &> /dev/null
if [ $? -eq 0 ];then
        echo "該用戶存在"
else
        echo "該用戶不存在"
fi

#!/bin/env bash
read -p "請輸入你要查詢的用戶名:" username
grep -w $username /etc/passwd &>/dev/null
if [ $? -eq 0 ]
then
    echo "該用戶已存在"
else
    echo "該用戶不存在"
fi

#!/bin/bash
read -p "請輸入你要檢查的用戶名:" name
id $name &>/dev/null
if [ $? -eq 0 ]
then
echo 用戶"$name"已經(jīng)存在
else
echo 用戶"$name"不存在
fi

#!/bin/env bash
#判斷用戶是否存在
read -p "請寫出用戶名" id
id $id
if [ $? -eq 0 ];then
        echo "用戶存在"
else
        echo "用戶不存在"
fi

#!/bin/env bash
read -p '請輸入用戶名:' username
id $username &>/dev/null
[ $? -eq 0 ] && echo '用戶存在' || echo '不存在'



㈡ 判斷軟件包是否安裝

需求2:用腳本判斷一個軟件包是否安裝,如果沒安裝則安裝它(假設(shè)本地yum已配合)


㈢ 判斷當(dāng)前主機(jī)的內(nèi)核版本

需求3:判斷當(dāng)前內(nèi)核主版本是否為2,且次版本是否大于等于6;如果都滿足則輸出當(dāng)前內(nèi)核版本

思路:
1. 先查看內(nèi)核的版本號    uname -r
2. 先將內(nèi)核的版本號保存到一個變量里,然后再根據(jù)需求截取出該變量的一部分:主版本和次版本
3. 根據(jù)需求進(jìn)步判斷


#!/bin/bash
kernel=`uname -r`
var1=`echo $kernel|cut -d. -f1`
var2=`echo $kernel|cut -d. -f2`
test $var1 -eq 2 -a $var2 -ge 6 && echo $kernel || echo "當(dāng)前內(nèi)核版本不符合要求"
或者
[ $var1 -eq 2 -a $var2 -ge 6 ] && echo $kernel || echo "當(dāng)前內(nèi)核版本不符合要求"
或者
[[ $var1 -eq 2 && $var2 -ge 6 ]] && echo $kernel || echo "當(dāng)前內(nèi)核版本不符合要求"

或者
#!/bin/bash
kernel=`uname -r`
test ${kernel:0:1} -eq 2 -a ${kernel:2:1} -ge 6 && echo $kernel || echo '不符合要求'

其他命令參考:
uname -r|grep ^2.[6-9] || echo '不符合要求'
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容