bash之條件測試及if語句

一、if語句:

單分支:

if CONDITION-TRUE; then

分支

fi

雙分支:

if CONDITION-TRUE; then

分支1

else

分支2

fi

多分支:

if CONDITION1-TRUE; then

分支1

elif CONDITION2-TRUE; then

分支2

...

else

分支n

fi


二、條件測試:

test EXPRESSION

[ EXPRESSION ]

` EXPRESSION `

COMMAND


2.1 測試表達式:

(1) 整數測試; 

(2) 字符串測試;

(3) 文件測試


2.2 整數測試:A, B

A -gt B: 大於

A -ge B: 大於等於

A -eq B: 等於

A -lt B: 小於

A -le B: 小於等於

A -ne B: 不等於  not equal to


2.3 字符串測試:A, B

A > B

A < B

A >= B

A <= B

A == B或A = B:等值比較

A != B: 不等於

-z A: 判斷A是否爲空;空則爲真,不空則假;

-n A:判斷A是否不空;不空則爲真,空則爲假;

=~

"$A" =~ PATTERN

如果變量A中保存的字符串能被PATTERN所匹配;即爲真;否則爲假;

2.4 文件測試:$file

-e $file: 是否存在;存在則爲真;

-a $file: 同上;棄用;

-f $file: 文件是否存在,且爲普通文件;

-d $file: 是否存在且爲目錄;

-h $file: 是否存在且爲符號鏈接文件;

-L $file:同上

-b $file: 是否存在且爲塊設備文件;

-c $file: 是否存在且爲字符設備文件;

-S $file: 是否存在且爲套接字文件:

-p $file: 是否存在且爲管道文件;


-r $file: 當前用戶對此文件是否擁有讀權限;

-w $file:                         寫

-x $file:                         執行權限;


-u $file: 文件是否擁有suid權限;

-g $file:文件是否擁有sgid權限;

-k $file: 文件是否擁有sticky權限;


-O $file: 當前用戶是否爲文件的屬主;

-G $file: 當前用戶是否屬於文件的屬組;


-N $file: 文件自從上一次被讀取之後,是否被修改過;

例如:

# cp /etc/fstab  /tmp/

# cat /tmp/fstab

# [ -N /tmp/fstab ]

# echo $?

1

# echo "hell world" >> /tmp/fstab

# [ -N /tmp/fstab ]

# echo $?

0

                  -s 測試文件是否不空,不空則爲真,空則爲假


$f1 -nt $f2: 文件f1是否比文件f2新;

$f1 -ot $f2: 文件f1是否比文件f2舊;

$f1 -ef $f2: f1和f2是否爲同一個文件的硬鏈接;


2.5 COMMAND用作條件:

(1) 使用命令執行結果;

(a) 使用命令引用

(b) 使用比較操作符


例如:

[ `id -u $username` -lt 500 ]
userid=`id -u $username`
[ $userid -lt 500 ]


(2) 使用命令的退出狀態碼

(a) 先運行命令;

(b) 退出狀態碼


引用方式兩種:

(a) if COMMAND; then

注意:COMMAND不能被命令引用;COMMAND的執行結果通常沒有意義,所以其結果通常(&>)被定向至/dev/null

(b) 先執行命令,後判斷退出狀態碼是否爲0

COMMAND

if [ $? -eq 0 ]


三、條件測試語法:

3.1 單分支:

             3.1.1 

if CONDITION; then

CMD1

CMD2

...

fi


例如:求100以內所有偶數之和;遍歷100以內所有正整數;

    #!/bin/bash
declare -i sum=0
for i in {1..100}; do
    if [[ $[$i%2] -eq 0 ]]; then
       let sum+=$i
    fi
done
echo "the sum of even is $sum"


練習1:傳遞一個參數給腳本,而後以此參數爲用戶名,添加此用戶;

方法一:

#!/bin/bash
#
if [ $# -ge 1 ]; then
        if ! id $1 &>/dev/null;then
        useradd $1
        fi
fi


方法二:

#!/bin/bash
     if !id $1 & >> null;then
         useradd $1
               else
               echo "the user exists"
               fiif可以嵌套:
if CONDITION1; then
if CONDITION2; then
CMD
fi
fi


    3.1.2 條件取反:

! CONDITION


練習2:寫一個腳本

(1) 添加用戶testuser1-tuser10;

(2) 用戶不存在時才添加;

(3) 統計真正添加的用戶數;

#!/bin/bash
#
declare -i newusers=0
for i in {1..10}; do
    if ! id testuser$i &> /dev/null; then
        useradd testuser$i
        let newusers++
    fi
done
echo "New users: $newusers."


練習3: 寫一個腳本

(1) 用ping命令測試172.16.100.X內的所有主機;

(2) 將在線的主機輸出出來;

#!/bin/bash
#
for i in {1..254}; do
    if ping -c1 -w1 172.16.100.$i &> /dev/null; then
        echo "172.16.100.$i is up."
    fi
done


3.2 雙分支:

if CONDITION-TRUE; then

分支1

else

分支2

fi


練習4: 寫一個腳本

  (1) 用ping命令測試172.16.100.X內的所有主機;

(2) 將所有主機的在線狀態輸出出來; 

#!/bin/bash
#!/f [ $# -ge 1 ]; then
        if ! id $1 &>/dev/null;then
        useradd $1
        fi
fibin/bash
#
for i in {1..255};do
        if  ping -c1 -w1 172.16.100.$i &>/dev/null;then
        echo the host: 172.16.100.$i is online
        else
        echo the host: 172.16.100.$i is offline
fi
done


練習5:寫一個腳本

(1) 傳遞兩個整數參數給腳本;

(2) 返回其較大一個;

#!/bin/bash
if [ $1 -lt $2 ]; then
       echo $2
   else
       echo $1
fi


練習6:寫一個腳本

(1) 傳遞兩個以上的整數給腳本;

(2) 返回其較大者;

#!/bin/bash
#
declare -i max=0
for i in $*; do
    if [ $i -gt $max ]; then
        max=$i
    fi
done
echo "max: $max."


練習7: 寫一個腳本

(1) 取得當前的主機名;

(2) 如果當前的主機名爲localhost,則將其修改爲www.magedu.com;否則,顯示其名稱;

#!/bin/bash
              source /etc/sysconfig/network       (讀取HOSTNAME配置文件,讓變量$HOSTNAME可以直接引用)
#echo $HOSTNAME
[ "$HOSTNAME" == "localhost"  ] && HOSTNAME="www.mage.com"
#/bin/hostname $HOSTNAME             (修改主機名,若在配置文件修改,可永久生效,但需要重啓;而hostname加newname可臨時修改;爲避免重啓,所以做臨時修改;而hostname前加/bin/;是因爲/bin/爲二進制程序配置文件庫;怕在腳本中直接用hostname修改不了)
hostname $HOSTNAME
echo $HOSTNAME
或者:
#!/bin/bash
source /etc/sysconfig/network
if [ $HOSTNAME == localhost ] ; then
    HOSTNAME="www.mage.com"
else
   echo $HOSTNAME
fi
hostname $HOSTNAME
echo $HOSTNAME


練習8:寫一個腳本

(1) 傳遞兩個文本文件路徑給腳本;

(2) 顯示兩個文件中空白行數較多的文件及其空白行數;

(3) 顯示兩個文件中總行數較多的文件及其行數;

#!/bin/bash
i=`grep "^$" $1 | wc -l`
j=`grep "^$" $2 | wc -l`
if [[ $i -gt $j ]]; then
    echo " the spaceline: $i"
else
    echo "the  spaceline: $j"
fi
k=`cat $1 | wc -l`
L=`cat $2 | wc -l`
if [[ $k -gt $L ]]; then
   echo "the file is $1 & the totalline is $k"
else
   echo "the file is $L & the totalline is $L"
fi


練習9:寫一個腳本

(1) 傳遞一個參數給腳本,此參數爲用戶名;

(2) 如果用戶存在,則執行如下任務

(a) 如果用戶的id號小於500,顯示其爲管理員或系統用戶;

(b) 否則,顯示其爲普通用戶;

(3) 如果用戶不存在,則添加之;

#!/bin/bash
#
if id $1 &> /dev/null; then
     userid=`id -u $1`
    if [ $userid -lt 500 ]; then
        echo "$1 is sysadmin or sysuser."
    else
        echo "A common user."
    fi
else
    useradd $1
    if [ $? -eq 0 ];then
        echo "Add user $1."
    else
        echo "Cannot add $1."
    fi
fi


3.3 多分支的if語句:

if CONDITION1-TRUE; then

分支1

elif CONDITION2-TRUE; then

分支2

elif CONDITION3-TRUE; then

分支3

...

else

分支n

fi


練習10:傳遞一個參數給腳本

如果參數爲quit,則顯示說要退出腳本;

如果參數爲yes,則顯示說繼續;

否則,則顯示爲無法識別;

#!/bin/bash
if [ "$1" == "quit" ];then         或者[ $1 == quit ]
       echo "exit"
elif [ "$1" == "yes" ];then
               echo "continue"
else
               echo "Not recognized"
fi


練習11:傳遞一個用戶名參數給腳本

(1) 如果用戶的id號爲0,則顯示爲管理員;

(2) 如果用戶的id號大於6000,則顯示爲guest; 

(3) 如果用戶的id號大於500,則顯示爲普通用戶;

(4) 如果用戶的id號大於0, 則顯示爲系統用戶;

(5) 否則,無法識別;

#!/bin/bash
#
if [ -z $1 ]; then 
        #echo "Usage: $(basen"
        echo "Not recognized"
        exit 1  
elif ! id $1 &> /dev/null; then
        #echo "Unknown....This isn't a user."
        echo "Not recognized"
        exit 2  
else
       userid=$(id -u $1)
       if [ $userid -eq 0 ]; then 
               echo "Admin user"
       elif [ $userid -gt 6000 ]; then 
               echo "Guest user"
       elif [ $userid -gt 500 ] && [ $userid -le 6000 ]; then 
               echo "Comon user"
       elif [ $userid -gt 0 ] && [ $userid -le 500 ]; then 
               echo "System user"
       fi      
fi

或者

#!/bin/bash
if [ $# -lt 1 ] ;then
echo "please input a user name"
exit 1
fi
if id $1 &> /dev/null ; then
uid=`id -u $1`
else
echo "no such user"
exit 2
fi
if [ "$uid" -eq 0 ] ;then
echo "The user is administrator"
elif [ "$uid" -gt 6000 ] ; then
echo "The user is guest"
elif [ "$uid" -gt 500 ] ; then
echo "The user is common"
elif [ "$uid" -gt 0 ] ; then
echo "The user is system "
else
echo "Cannot found"
fi


    3.4 文件測試練習    

練習12:寫一個腳本,傳遞一個文件路徑參數給腳本

(1) 存在,則顯示有此文件;

(2) 否則,則顯示無此文件

      #!/bin/bash
if [ -z $1 ];then
   echo "you entered nothing"
      exit 1
else
   if [ -e $1 ]; then
      echo "the file exists"
   else
      echo "the file doesn't exist"
  fi
fi


練習13:寫一個腳本,傳遞一個文件路徑參數給腳本

(1) 如果腳本無參數,則顯示必須給至少一個參數,退出腳本;退出碼5;

(2) 路徑指向的文件如果不存在,則直接退出腳本;退出碼爲6;

(3) 判斷文件類型:

(a) 如果是普通文件,則顯示爲"common file";

(b) 如果是目錄,則顯示爲"directory";

(c) 如果是符號鏈接,則顯示爲"symbolic link file";

(d) 如果是塊設備,則顯示爲“block device file";

(e) 如果是字符設備,則顯示爲"character device file";

(f) 否則,則顯示爲“unkown”;

#!/bin/bash
#
if [ $# -lt 1 ]; then
    echo "At least one argument."
    exit 5
fi
if [ ! -e $1 ]; then
    echo "No such file."
    exit 6
fi
if [ -f $1 ]; then
    echo "common file."
elif [ -d $1 ]; then
    echo "directory."
elif [ -L $1 ]; then
    echo "Symbolic link."
elif [ -b $1 ]; then
    echo "block device."
elif [ -c $1 ]; then
    echo "character device."
else
    echo "unkown type."
fi


練習14:寫一個腳本,其使用格式如下所示(其中所有的script.sh均爲用戶給定的腳本名稱,其要跟隨腳本名稱變化):

script.sh {start|stop|restart|status} 

(1) 調用時至少傳遞一個參數;否則,則顯示幫助信息,並退出腳本;

(2) 如果參數爲“start”, 則創建空文件/var/lock/subsys/script.sh,並顯示“starting script.sh successfully.”;

(3) 如果參數爲“stop”,則刪除空文件/var/lock/subsys/script.sh,並顯示“stopping script.sh successfully.”;

(4) 如果參數爲“restart”,則刪除空文件/var/lock/subsys/script.sh,並顯示“stopping script.sh successfully.”;而後重新創建之,並顯示“restarting script.sh successfully.”;

(5) 如果參數爲“status”,則

(a) 如果文件/var/lock/subsys/script.sh文件存在,則顯示“running”;

(b) 否則,則顯示爲"stopped"

(6) 其它任意參數,均顯示幫助信息後退出;幫助信息格式爲命令使用格式;

 
#!/bin/bash
#
# chkconfig: 2345 95 5                    
# description: test service script        此兩行爲開機啓動腳本格式;可以cp到腳本配置文件 /etc/init.d 裏面;但需要先給其權限;然後再拷貝;然後在命令行鍵入chkfig -add script.sh 運行;則可生效
#
prog=`basename $0`                       $0是從當下目錄到其有$0腳本的完全路徑
lockfile=/var/lock/subsys/$prog
if [ $# -lt 1 ]; then
    echo "Usage: $prog {start|stop|restart|status}"
    exit 1
fi
if [ "$1" == 'start' ]; then
    if [ -e $lockfile ]; then
echo "$prog is aleady running."
exit 1
    else
touch $lockfile
echo "Starting $prog succefully."
    fi
elif [ "$1" == 'stop' ]; then
    if [ -e $lockfile ]; then
rm -f $lockfile
echo "Stopping $prog succefully."
    else
echo "$prog is not running."
exit 1
    fi

elif [ "$1" == 'restart' ]; then
    if [ -e $lockfile ]; then
rm -f $lockfile
echo "Stopping $prog succefully."
touch $lockfile
echo "Starting $prog succefully."
    else
touch $lockfile
echo "Starting $prog succefully."
    fi
elif [ "$1" == 'status' ];then
    if [ -e $lockfile ];then
echo "$prog is running."
    else
echo "$prog is stopped."
    fi
else
    echo "Usage: $prog {start|restart|status|stop}"
    exit 1
fi


四、組合測試條件:

4.1 給條件添加邏輯操作符;

或, -o: [ -z "$hostname" -o "$hostname" == 'localhost' ]

與, -a: [ $uid -gt 0 -a $uid -lt 500 ]

非:[ ! EXPRESSION ]


練習15:寫一個腳本,取得當前的主機名,判斷      答案參照552練習4題;

(1) 如果主機名爲空或爲"localhost",則將其命名爲stuX.magedu.com;

(2) 否則,則顯示主機名即可;

#!/bin/bash
#
hostname=`hostname`
if [ "$hostname" == 'localhost' -o -z "$hostname" ]; then
    hostname stu100.magedu.com
    #echo "stu100.magedu.com" > /proc/sys/kernel/hostname
else
    echo "The hostname is: $hostname."
fi


練習16:寫一個腳本,傳遞一個參數給腳本;此參數爲用戶名

(1) 如果用戶不存在,則直接退出腳本;

(2) 如果用戶存在,

id=0,則顯示爲“system admin”

0<id<500,則顯示爲“system user”

id>=500,則顯示爲“Common user.”

#!/bin/bash
#
if ! id $1 &> /dev/null; then
    echo "No such user."
    exit 1
fi
uid=$(id -u $1)   注意:大寫UID在此處用可能有會衝突,也可找其他字母代替
if [ $uid -eq 0 ]; then
    echo "Sys Admin."
elif [ $uid -gt 0 -a $uid -lt 500 ];then
    echo "Sys User."
else
    echo "Common User."
fi


練習17:寫一個腳本,傳遞一個參數給腳本;此參數爲用戶名

(1) 如果用戶不存在,則直接退出腳本;

(2) 如果用戶的id號大於等於500,且其shell爲“以sh結尾的”類型,則顯示“a user can log system.”;否則,顯示用戶無法登錄;

#!/bin/bash
#
if ! id $1 &> /dev/null; then
    echo "No such user."
    exit 1
fi
if [[ `id -u $1` -ge 500 ]] && [[ `grep "^$1\>" /etc/passwd | cut -d: -f7` =~ /bin/.*sh$ ]]; then
    echo "a user can log system."
else
    echo "a user cannot log."
fi

或者

#!/bin/bash
if [ $# -lt 1 ];then
echo "At least one argument"
        exit 1
fi
if ! id $1 &>/dev/null;then
echo "the user does not exist"
        exit 2
fi
if id $1 &>/dev/null;then
if [[ `id -u $1` -ge 500 ]] && [[ `grep 'bash$' /etc/passwd | cut -d: -f7` ]];then
echo "a user can log system"
else
echo "can not login"
fi
fi


4.2 組合測試條件:短路操作符

與:COMMAND1 && COMMAND2

COMMAND1的退出狀態如果爲假,則COMMAND2不用運行,即可有最終結果;

或:COMMAND1 || COMMAND2

COMMAND1的退出狀態如果爲真,則COMMAND2不用運行,即可有最終結果;

非:! COMMAND


[ ! -d /tmp/test ] && mkdir /tmp/test

   [ -d /tmp/test ] || mkdir /tmp/test


練習18:寫一個腳本,完成如下任務:

(1) 如果httpd進程或nginx進程處於運行中,則顯示“web server started.”,並顯示其監聽的端口;

(2) 否則顯示“no web server.”;

         (if pidof httpd &> /dev/null && pidof nginx &> /dev/null;) 


#!/bin/bash
h=`netstat -lntp | grep 'httpd' | cut -d':' -f4`
n=`ss -tnlp | grep 'nginx' | cut -d":" -f2 | cut -d" " -f1`
if pidof httpd &>/dev/null;then
  #   netstat -tnlp | grep 'httpd' | cut -d':' -f4    
       echo "the httpd web server started"
    echo "the httpd listenning port is $h"
  elif pidof nginx &>/dev/null;then
   #         ss -tnlp | grep 'nginx' | cut -d":" -f2 | cut -d" " -f1
   #  netstat -ntpl | grep 'nginx' | cut -d: -f2 | cut -d" " -f1   
   echo "the nginx web server started"
echo "the nginx listenning port is $n"
else
echo "No web server"
fi

         上面是各種方法的組合,可以靈活轉換


五、交互式腳本:

read [OPTIONS] [name ...]

用法示例:

[root@node3 ~]# read A
hello
[root@node3 ~]# echo $A
hello
[root@node3 ~]# read A B C
how old are you?
[root@node3 ~]# echo $A
how
[root@node3 ~]# echo $C
are you?


-p "PROMPT"  提示信息

-t #: 超時時長


給變量以默認值:

[ -z "$VAR" ] && VAR=VALUE


練習19:顯示如下菜單給用戶

cpu) show cpu infomation;

mem) show memory infomation;

disk) show disk infomation;

*) quit

提示用戶鍵入選項:

(1) cpu: 顯示CPU相關的信息

(2) mem: 顯示內存相關的信息

(3) disk: 列出磁盤設備

(4) 其它任何信息,即爲退出腳本

#!/bin/bash
#
cat << EOF
cpu) show cpu infomation;
mem) show memory infomation;
disk) show disk infomation;
*) quit
=================================================================
EOF
read -p "Your  choice: " choice
if [[ "$choice" == 'cpu' ]]; then
    lscpu
elif [[ "$choice" == 'mem' ]]; then
    free -m
elif [[ "$choice" == 'disk' ]]; then
    fdisk -l /dev/sd[a-z]
else
    echo "quit"
    exit 0
fi


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章