20.5 shell腳本中的邏輯判斷
格式1:if 條件 ; then 語句; fi
[root@test220 ~]# a=5
[root@test220 ~]# if [ $a -gt 3 ]
> then
> echo ok
> fi
ok
[root@test220 ~]# if [ $a -gt 3 ]; then echo ok; fi
ok
改成shell腳本
[root@test220 script]# vim if1.sh
#!/bin/bash
a=5
[ $a -gt 3 ]
then
echo ok
fi
調試;
[root@aiker02 script]# sh -x !$
sh -x if1.sh
+ a=5
+ '[' 5 -gt 3 ']'
+ echo ok
ok
[root@test220 ~]# for i in `seq 1 5`;do echo $i;done;
1
2
3
4
5
[root@test220 ~]# for i in `seq 1 5`
> do echo $i
> done
1
2
3
4
5
格式2:if 條件; then 語句; else 語句; fi
[root@test220 script]# vim if2.sh
#!/bin/bash
a=3
if [ $a -gt 3 ]
then
echo ok
else
echo nook!
fi
[root@aiker02 script]# sh -x !$
sh -x if2.sh
+ a=3
+ '[' 3 -gt 3 ']'
+ echo 'nook!'
nook!
格式3:if …; then … ;elif …; then …; else …; fi
[root@aiker02 script]# vim if3.sh
#!/bin/bash
a=3
if [ $a -gt 4 ]
then
echo ">4"
elif [ $a -lt 6 ]
then
echo " <6 && >1"
else
echo nook!
fi
[root@aiker02 script]# sh -x !$
sh -x if3.sh
+ a=3
+ '[' 3 -gt 4 ']'
+ '[' 3 -lt 6 ']'
+ echo ' <6 && >1'
<6 && >1
邏輯判斷表達式:
if [ $a -gt $b ]; if [ $a -lt 5 ]; if [ $b -eq 10 ]等
-gt(>); -lt(<); -ge(>=); -le(<=);-eq(==); -ne(!=) 注意到處都是空格
參數 | 說明 |
---|---|
-eq | 等於則爲真 |
-ne | 不等於則爲真 |
-gt | 大於則爲真 |
-ge | 大於等於則爲真 |
-lt | 小於則爲真 |
-le | 小於等於則爲真 |
[root@aiker02 script]# a=3
[root@aiker02 script]# if (($a>1));then echo ok;fi
ok
可以使用 && || 結合多個條件
if [ $a -gt 5 ] && [ $a -lt 10 ]; then
if [ $b -gt 5 ] || [ $b -lt 3 ]; then
20.6 文件目錄屬性判斷
[ -f file ]判斷是否是普通文件,且存在
[root@aiker02 script]# vim test1.sh
#!/bin/bash
f='/tmp/aiker'
if [ -f $f ]
then
echo $f exist
else
touch $f
fi
[root@aiker02 script]# sh -x test1.sh
+ f=/tmp/aiker
+ '[' -f /tmp/aiker ']'
+ touch /tmp/aiker
[root@aiker02 script]# sh -x test1.sh
+ f=/tmp/aiker
+ '[' -f /tmp/aiker ']'
+ echo /tmp/aiker exist
/tmp/aiker exist
[ -d file ] 判斷是否是目錄,且存在
[root@aiker02 script]# vim testd.sh
#!/bin/bash
f='/tmp/aiker'
if [ -d $f ]
then
echo $f exist
else
touch $f
fi
[root@aiker02 script]# sh -x !$
sh -x testd.sh
+ f=/tmp/aiker
+ '[' -d /tmp/aiker ']'
+ touch /tmp/aiker
[ -e file ] 判斷文件或目錄是否存在
#!/bin/bash
f='/tmp/aiker'
if [ -e $f ]
then
echo $f exist
else
touch $f
fi
[root@aiker02 script]# sh -x !$
sh -x teste.sh
+ f=/tmp/aiker
+ '[' -e /tmp/aiker ']'
+ echo /tmp/aiker exist
/tmp/aiker exist
[ -r file ] 判斷文件是否可讀
[root@aiker02 script]# vim testr.sh
#!/bin/bash
f='/tmp/aiker'
if [ -r $f ]
then
echo $f is readable
else
echo $f is unreadable
fi
[root@aiker02 script]# sh -x !$
sh -x testr.sh
+ f=/tmp/aiker
+ '[' -r /tmp/aiker ']'
+ echo /tmp/aiker is readable
/tmp/aiker is readable
[ -w file ] 判斷文件是否可寫
[root@aiker02 script]# vim testw.sh
#!/bin/bash
f='/tmp/aiker'
if [ -w $f ]
then
echo $f is writeable
else
echo $f is not writeable
fi
[root@aiker02 script]# sh -x !$
sh -x testw.sh
+ f=/tmp/aiker
+ '[' -w /tmp/aiker ']'
+ echo /tmp/aiker is writeable
/tmp/aiker is writeable
[ -x file ] 判斷文件是否可執行
[root@aiker02 script]# vim testx.sh
#!/bin/bash
f='/tmp/aiker'
if [ -x $f ]
then
echo $f is exe file
else
echo $f is not exe file
fi
[root@aiker02 script]# sh -x !$
sh -x testx.sh
+ f=/tmp/aiker
+ '[' -x /tmp/aiker ']'
+ echo /tmp/aiker is not exe file
/tmp/aiker is not exe file
[root@aiker02 script]# cat !$
cat testf2.sh
#!/bin/bash
f='/tmp/aiker'
[ -f $f ] && rm -f $f ##前面的執行成功就執行後面的
[ -f $f ] || touch $f ##前面的不成功才執行後面的
if [ -f $f ]
then
rm -f $f
else
touch $f
fi
if [ ! -f $f ] ##!是取非,!f不存在
then
touch $f
fi
[root@aiker02 script]# sh -x !$
sh -x testf2.sh
+ f=/tmp/aiker
+ '[' -f /tmp/aiker ']'
+ rm -f /tmp/aiker
+ '[' -f /tmp/aiker ']'
+ touch /tmp/aiker
+ '[' -f /tmp/aiker ']'
+ rm -f /tmp/aiker
+ '[' '!' -f /tmp/aiker ']'
+ touch /tmp/aiker
<table>
<tbody>
<tr>
<td width="100">測試的標誌</font></td><td>代表意義</font></td>
</tr>
<tr>
<td colspan="2">1. 關於某個檔名的『文件類型』判斷,如 test -e filename 表示存在否</font></td>
</tr>
<tr>
<td>-e</td><td>該『檔名』是否存在?(常用)</td>
</tr>
<tr>
<td>-f</td><td>該『檔名』是否存在且爲文件(file)?(常用)</td>
</tr>
<tr>
<td>-d</td><td>該『檔名』是否存在且爲目錄(directory)?(常用)</td>
</tr>
<tr>
<td>-b</td><td>該『檔名』是否存在且爲一個 block device 裝置?</td>
</tr>
<tr>
<td>-c</td><td>該『檔名』是否存在且爲一個 character device 裝置?</td>
</tr>
<tr>
<td>-S</td><td>該『檔名』是否存在且爲一個 Socket 文件?</td>
</tr>
<tr>
<td>-p</td><td>該『檔名』是否存在且爲一個 FIFO (pipe) 文件?</td>
</tr>
<tr>
<td>-L</td><td>該『檔名』是否存在且爲一個連結檔?</td>
</tr>
<tr>
<td colspan="2">2. 關於文件的權限偵測,如 test -r filename 表示可讀否 (但 root 權限常有例外)</font></td>
</tr>
<tr>
<td>-r</td><td>偵測該檔名是否存在且具有『可讀』的權限?</td>
</tr>
<tr>
<td>-w</td><td>偵測該檔名是否存在且具有『可寫』的權限?</td>
</tr>
<tr>
<td>-x</td><td>偵測該檔名是否存在且具有『可運行』的權限?</td>
</tr>
<tr>
<td>-u</td><td>偵測該檔名是否存在且具有『SUID』的屬性?</td>
</tr>
<tr>
<td>-g</td><td>偵測該檔名是否存在且具有『SGID』的屬性?</td>
</tr>
<tr>
<td>-k</td><td>偵測該檔名是否存在且具有『Sticky bit』的屬性?</td>
</tr>
<tr>
<td>-s</td><td>偵測該檔名是否存在且爲『非空白文件』?</td>
</tr>
<tr>
<td colspan="2">3. 兩個文件之間的比較,如: test file1 -nt file2</font></td>
</tr>
<tr>
<td>-nt</td><td>(newer than)判斷 file1 是否比 file2 新</td>
</tr>
<tr>
<td>-ot</td><td>(older than)判斷 file1 是否比 file2 舊</td>
</tr>
<tr>
<td>-ef</td><td>判斷 file1 與 file2 是否爲同一文件,可用在判斷 hard link 的判定上。
主要意義在判定,兩個文件是否均指向同一個 inode 哩!</td>
</tr>
<tr>
<td colspan="2">4. 關於兩個整數之間的判定,例如 test n1 -eq n2</font></td>
</tr>
<tr>
<td>-eq</td><td>兩數值相等 (equal)</td>
</tr>
<tr>
<td>-ne</td><td>兩數值不等 (not equal)</td>
</tr>
<tr>
<td>-gt</td><td>n1 大於 n2 (greater than)</td>
</tr>
<tr>
<td>-lt</td><td>n1 小於 n2 (less than)</td>
</tr>
<tr>
<td>-ge</td><td>n1 大於等於 n2 (greater than or equal)</td>
</tr>
<tr>
<td>-le</td><td>n1 小於等於 n2 (less than or equal)</td>
</tr>
<tr>
<td colspan="2">5. 判定字串的數據</font></td>
</tr>
<tr>
<td>test -z string</td><td>判定字串是否爲 0 ?若 string 爲空字串,則爲 true</td>
</tr>
<tr>
<td>test -n string</td><td>判定字串是否非爲 0 ?若 string 爲空字串,則爲 false。<br>注: -n 亦可省略</td>
</tr>
<tr>
<td>test str1 = str2</td><td>判定 str1 是否等於 str2 ,若相等,則回傳 true</td>
</tr>
<tr>
<td>test str1 != str2</td><td>判定 str1 是否不等於 str2 ,若相等,則回傳 false</td>
</tr>
<tr>
<td colspan="2">6. 多重條件判定,例如: test -r filename -a -x filename</font></td>
</tr>
<tr>
<td>-a</td><td>(and)兩狀況同時成立!例如 test -r file -a -x file,則 file 同時具有 r 與
x 權限時,纔回傳 true。</td>
</tr>
<tr>
<td>-o</td><td>(or)兩狀況任何一個成立!例如 test -r file -o -x file,則 file 具有 r 或
x 權限時,就可回傳 true。</td>
</tr>
<tr>
<td>!</td><td>反相狀態,如 test ! -x file ,當 file 不具有 x 時,回傳 true</td>
</tr>
</tbody>
</table>
if-then語句,格式如下:
if command_1
then command_2
command_3
fi command_4
在if-then語句中使用了命令返回碼$?,即當command_1執行成功時才執行command_2和 command_3,而command_4總是執行 ,例:
在備份成功時刪除原始文件:
if l s - a | cpi o - o > / dev/ rm t / 0h
then
rm - rf *
fi
測試條件之否定,使用!
測試條件之邏輯運算
-a And
-o Or
例:
test -r empty -a -s empty
進行test測試的標準方法
因爲test命令在 shell編程中佔有很重要的地位,爲了使shell能 同其他編程語言一樣 便於閱讀和組織, Bourne Shell在使用test 測試時使用了另一種方法:用方括號將整個 test測試括起來:
例:
int1=4
[ $int1 -gt 2 ]
echo $?
0
20.7 if特殊用法
if [ -z "$a" ] 這個表示當變量a的值爲空時會怎麼樣
[root@aiker02 ~]# vim !$
vim testz0.sh
#!/bin/bash
n=`wc -l /tmp/aikerv | awk '{print $1}'`
if [ -z "$n" ]
then
echo error
exit 1
else
if [ $n -gt 100 ]
then
echo $n over 100 hang.
fi
fi
[root@aiker02 ~]# sh -x testz0.sh
++ awk '{print $1}'
++ wc -l /tmp/aikerv
+ n=1
+ '[' -z 1 ']'
+ '[' 1 -gt 100 ']'
或者
[root@aiker02 ~]# vim testz.sh
#!/bin/bash
n=`wc -l /tmp/aikerv | awk '{print $1}'`
if [ -z "$n" ]
then
echo error
exit 1
elif [ $n -gt 100 ]
then
echo $n over 100 hang.
fi
[root@aiker02 ~]# sh -x testz.sh
++ awk '{print $1}'
++ wc -l /tmp/aikerv
+ n=1
+ '[' -z 1 ']'
+ '[' 1 -gt 100 ']'
if [ -n "$a" ] 表示當變量a的值不爲空
[root@aiker02 ~]# if [ -n autosshd ]; then echo OK; fi #判斷文件內容不爲空,如果爲文件,不用雙引號引起
OK
[root@aiker02 ~]# if [ -n "$b" ]; then echo $b; else echo "b is null"; fi ##如果使用變量,一定要“”
b is null
if grep -q '123' 1.txt; then 表示如果1.txt中含有'123'的行時會怎麼樣
[root@aiker02 ~]# grep -w 'operator' /etc/passwd #-w精確過濾
operator:x:11:0:operator:/root:/sbin/nologin
[root@aiker02 ~]# if grep -w 'operator' /etc/passwd; then echo "operator is exist."; fi ##grep輸出了結果
operator:x:11:0:operator:/root:/sbin/nologin
operator is exist.
[root@aiker02 ~]# if grep -wq 'operator' /etc/passwd; then echo "operator is exist."; fi ##-q不輸出過程
operator is exist.
if ! grep -wq 'operator' /etc/passwd; then echo "operator is not exist" && useradd operator; fi ##不存在operator
if [ ! -e file ]; then 表示文件不存在時會怎麼樣
[root@aiker02 script]# vim testne.sh ##!取反
#!/bin/bash
f='/tmp/aiker'
if [ ! -e $f ]
then
echo $f is not exist
touch $f
else
echo $f is exist
fi
[root@aiker02 script]# sh -x testne.sh
+ f=/tmp/aiker
+ '[' '!' -e /tmp/aiker ']'
+ echo /tmp/aiker is exist
/tmp/aiker is exist
if (($a<1)); then …等同於 if [ $a -lt 1 ]; then…
[root@aiker02 script]# vim testlt.sh
#!/bin/bash
a=6
if (($a<5))
then
echo $a 'is < 5'
elif [ $a -lt 10 ]
then
b=$(($a+1))
echo $b
fi
[root@aiker02 script]# sh -x testlt.sh
+ a=6
+ (( 6<5 ))
+ '[' 6 -lt 10 ']'
+ b=7
+ echo 7
7
[ ] 中不能使用<,>,==,!=,>=,<=這樣的符號,(())可以使用,[[]]可以使用,可以用[[]]代替[]
if嵌套及elif結構
if command
then command
else
if command
then command
else
if command
then command
fi
fi
fi
改進:使用elif結構
if command
then command
elif command
then command
elif command
then command
fi
20.8/20.9 case判斷
格式
case 變量名 in
value1)
command
;;
value2)
command
;;
*)
commond
;;
esac
在case程序中,可以在條件中使用|,表示或的意思, 比如
2|3)
command
;;
shell腳本案例
#!/bin/bash
read -p "Please input a number: " n
if [ -z "$n" ] ##如果爲空,提示輸入數字
then
echo "Please input a number."
exit 1
fi
n1=`echo $n|sed 's/[0-9]//g'` #判斷輸入的是否爲數字,如果是數字就替換爲空
if [ -n "$n1" ] ##判斷是否爲空,如果不爲空就提示輸入數字,注意-n 變量需要“”
then
echo "Please input a number."
exit 1
fi
if [ $n -lt 60 ] && [ $n -ge 0 ]
then
tag=1 ##tag打標記
elif [ $n -ge 60 ] && [ $n -lt 80 ]
then
tag=2
elif [ $n -ge 80 ] && [ $n -lt 90 ]
then
tag=3
elif [ $n -ge 90 ] && [ $n -le 100 ]
then
tag=4
else
tag=0
fi
case $tag in
1)
echo "is bad"
;;
2)
echo "ok"
;;
3)
echo "good"
;;
4)
echo "very good"
;;
*)
echo "The number range is 0-100."
;;
esac
[root@aiker02 script]# cat !$
cat case0.sh
#!/bin/bash
read -p "Please input a number: " n
if [ -z "$n" ]
then
echo "Please input a number."
exit 1
fi
n1=`echo $n|sed 's/[0-9]//g'`
if [ -n "$n1" ]
then
echo "Please input a number."
exit 1
fi
if [ $n -lt 60 ] && [ $n -ge 0 ]
then
tag=1
elif [ $n -ge 60 ] && [ $n -lt 80 ]
then
tag=2
elif [ $n -ge 80 ] && [ $n -lt 90 ]
then
tag=3
elif [ $n -ge 90 ] && [ $n -le 100 ]
then
tag=4
else
tag=0
fi
case $tag in
1)
echo "is bad"
;;
2)
echo "ok"
;;
3)
echo "good"
;;
4)
echo "very good"
;;
*)
echo "The number range is 0-100."
;;
esac
[root@aiker02 script]# sh -x !$
sh -x case0.sh
+ read -p 'Please input a number: ' n
Please input a number: 49
+ '[' -z 49 ']'
++ sed 's/[0-9]//g'
++ echo 49
+ n1=
+ '[' -n '' ']'
+ '[' 49 -lt 60 ']'
+ '[' 49 -ge 0 ']'
+ tag=1
+ case $tag in
+ echo 'is bad'
is bad
[root@aiker02 script]# sh -x case0.sh
+ read -p 'Please input a number: ' n
Please input a number: 6+^H0
+ '[' -z $'6+\b0' ']'
++ sed 's/[0-9]//g'
++ echo $'6+\b0'
+ n1=$'+\b'
+ '[' -n $'+\b' ']'
+ echo 'Please input a number.'
Please input a number.
+ exit 1
[root@aiker02 script]# sh -x case0.sh
+ read -p 'Please input a number: ' n
Please input a number: 60
+ '[' -z 60 ']'
++ sed 's/[0-9]//g'
++ echo 60
+ n1=
+ '[' -n '' ']'
+ '[' 60 -lt 60 ']'
+ '[' 60 -ge 60 ']'
+ '[' 60 -lt 80 ']'
+ tag=2
+ case $tag in
+ echo ok
ok
[root@aiker02 script]# sh -x case0.sh
+ read -p 'Please input a number: ' n
Please input a number: 500
+ '[' -z 500 ']'
++ sed 's/[0-9]//g'
++ echo 500
+ n1=
+ '[' -n '' ']'
+ '[' 500 -lt 60 ']'
+ '[' 500 -ge 60 ']'
+ '[' 500 -lt 80 ']'
+ '[' 500 -ge 80 ']'
+ '[' 500 -lt 90 ']'
+ '[' 500 -ge 90 ']'
+ '[' 500 -le 100 ']'
+ tag=0
+ case $tag in
+ echo 'The number range is 0-100.'
The number range is 0-100.
case結構 :
case value in
pattern1)
command
command;;
pattern2)
command
command;;
...
patternn)
command
esac
case語句只執行第一個匹配模式,
例:
case "$CHOICE" in
1|R) echo "Restore";;
2|B) echo "Backup";;
3|U) echo "Unload";;
*) echo "Sorry $CHOICE is not a valid choice
exit 1
esac