條件測試方法綜述


test條件測試的簡單語法及測試

范例6-1 測試文件(在test命令中使用-f選項:文件存在且為不同文件則表達式成立)
[root@adminset ~]# test -f file && echo true || echo false false [root@adminset ~]# touch file [root@adminset ~]# test -f file && echo true || echo false true
范例6-2 測試字符串(在test命令中使用-z選項(如果測試字符串的長度為0,則表達式成立)
[root@adminset ~]# test -z "luoahong" && ehco 1 || echo 0 0 [root@adminset ~]# char="luoahong" 0 [root@adminset ~]# test -z "$char" && echo 1 || echo 0 0 [root@adminset ~]# char="" [root@adminset ~]# test -z "$char" && echo 1 || echo 0 1
結論:test命令測試的功能很強大,但是和[] [[]]的功能有所重合,因此,在實際工作中選擇一種適合自己的語法就好了,對於其他的語法,能讀懂別人寫的腳本就可以了
[](中括號)條件測試語法及示例
范例6-3 測試文件(利用[]加-f 選項 文件存在且為普通文件則表達式成立)
[root@adminset ~]# [ -f /tmp/luoahong.txt ] && echo 1 ||echo 0 0 [root@adminset ~]# touch /tmp/luoahong.txt [root@adminset ~]# [ -f /tmp/luoahong.txt ] && echo 1 ||echo 0 1 [root@adminset ~]# [ -f /tmp/luoahong.txt ] ||echo 0 [root@adminset ~]# [ -f /tmp/luoahong1.txt ] ||echo 0 0 [root@adminset ~]# [ -f /tmp/luoahong1.txt ] ||echo 0 0 [root@adminset ~]# touch /tmp/luoahong1.txt [root@adminset ~]# [ -f /tmp/luoahong1.txt ] ||echo 0 [root@adminset ~]# rm -f /tmp/luoahong1.txt [root@adminset ~]# [ -f /tmp/luoahong1.txt ] ||echo 0 0
提示:[]命令的選項和test的命令的選項是通用的,因此,使用[]時的參數選項可以通過man test命令獲的幫助
文件測試表達式
范例6-5:文件屬性條件表達式測試實踐
[root@adminset ~]# ls -l luoahong -rw-r--r-- 1 root root 0 Jun 14 07:48 luoahong [root@adminset ~]# [ -r luoahong ] && echo 1 ||echo 0 1 #測試luoahong是否可讀 [root@adminset ~]# [ -w luoahong ] && echo 1 ||echo 0 1 #測試luoahong是否可寫 [root@adminset ~]# [ -x luoahong ] && echo 1 ||echo 0 0 #測試luoahong是否可執行 [root@adminset ~]# chmod 001 luoahong [root@adminset ~]# ls -l luoahong ---------x 1 root root 0 Jun 14 07:48 luoahong #修改后的結果 [root@adminset ~]# [ -w luoahong ] && echo 1 ||echo 0 1 #用戶權限位明明沒有w,為什么還是返回1呢? [root@adminset ~]# echo 'echo test' >oldboy #因為確實可以寫啊,這是root用戶比較特殊的地方 [root@adminset ~]# [ -r luoahong ] && echo 1 ||echo 0 1 #用戶權限位明明沒有r,為什么還是返回1呢? [root@adminset ~]# echo 'echo test' >luoahong [root@adminset ~]#cat luoahong echo test #因為確實可以讀啊,這是root用戶比較特殊的地方。 [root@adminset ~]# [ -x luoahong ] && echo 1 ||echo 0 1 [root@adminset ~]# ./luoahong [root@adminset ~]# ./luoahong test #可執行
提示:測試文件的讀、寫、執行等屬性,不光是根據文件屬性rwx的表示來判斷,
還要看當前執行的用戶是否真的可以按照對應的權限操作該文件
測試shell變量示例
root@adminset ~]# file1=/etc/services;file2=/etc/rc.local [root@adminset ~]# echo $file1 $file2 /etc/services /etc/rc.local
范例:對單個文件變量進行測試
[root@adminset ~]# [ -f "$file1" ] && echo 1 || echo 0 1 [root@adminset ~]# [ -d "$file1" ] && echo 1 || echo 0 0 [root@adminset ~]# [ -s "$file1" ] && echo 1 || echo 0 1 [root@adminset ~]# [ -e "$file1" ] && echo 1 || echo 0 1 [root@adminset ~]# [root@adminset ~]#
范例:對單個目錄或文件進行測試
[root@adminset ~]# [ -e /etc ] && echo 1 || echo 0 1 [root@adminset ~]# [ -w /etc/serbices ] && echo 1 || echo 0 0 [root@adminset ~]# su - luoahong [luoahong@adminset ~]$ [ -w /etc/servies ] && echo 1 || echo 0 0 #文件不可寫,所以返回0
范例:測試變量的特殊寫法及問題
用測試變量時,如果被測試的變量不加雙引號,那么測試結果可能會不時正確的示例如下:
[luoahong@adminset ~]$ echo $tyx #這是一個不存在的變量,如果讀者已經定義、則可以執行unset取消 [luoahong@adminset ~]$ [ -f $tyx ] && echo 1 || echo 0 1 #命名$tyx變量不存在內容還返回1,邏輯就不對了 [luoahong@adminset ~]$ [ -f "$tyx" ] && echo 1 || echo 0 0 #加了雙引號就返回0,邏輯就對了
如果是文件實體路徑,那么加引號與不加引號的結果時一樣的:
[luoahong@adminset ~]$ [ -f "/etc/services" ] && echo 1 || echo 0 1 [luoahong@adminset ~]$ [ -f /etc/services ] && echo 1 || echo 0 1
范例: 在生產環境下,系統NFS啟動腳本的條件測試
more /etc/init.d/nfs # Source networking configuration. [ -f /etc/sysconfig/network ] && . /etc/sysconfig/network # Check for and source configuration file otherwise set defaults [ -f /etc/sysconfig/nfs ] && . /etc/sysconfig/nfs # Remote quota server [ -z "$RQUOTAD" ] && RQUOTAD=`type -path rpc.rquotad`
特別提示:系統腳本時我們學習編程的第一標桿,新手要多參考腳本來學習,雖然有些腳本也不是特別規范
范例:實現系統bind啟動腳本named
[luoahong@adminset ~]$ [ -r /etc/sysyconfig/network ] && ./etc/sysconfig/network #若文件存在且可讀,則加載/etc/sysconfig/network [luoahong@adminset ~]$ [ -x /usr/sbin/$named ] || exit 5
范例:寫出簡單高效的測試文件
在做測試判斷時,不一定非要按照"前面的操作成功了如何,否則如何"的方法來進行。直接做部分判斷,有時看起來更簡潔
[luoahong@adminset ~]$ [ -x luoahong ] && echo 1 #如果luoahong可執行,則輸出1;如果不可執行,則不做任何輸出 [luoahong@adminset ~]$ [ -f /etc ] && echo 1 [luoahong@adminset ~]$ [ -f /etc ] && echo 0 #如果l/etc 是文件這一點不成立,則輸出0,如果成立則不做任何輸出
范例:實現系統腳本/etc/init.d/nfs
[luoahong@adminset ~]$ sed -n '44,50p' /etc/init.d/nfs
# Check that networking is up.
[ "${NETWORKING}" != "yes" ] && exit 6
#如果${NETWORKING}的變量內容不等於yes,則退出
[ -x /usr/sbin/rpc.nfsd ] || exit 5
#如果/usr/sbin/rpc.nfsd的腳本不可執行,則以返回值5退出腳本。如果可執行,則不做任何輸出
[ -x /usr/sbin/rpc.mountd ] || exit 5
[ -x /usr/sbin/exportfs ] || exit 5
特殊表達式測試案例
范例:當條件不成立是,執行大括號里的多條命令,這里要使用邏輯操作符||
[root@adminset 06]# sh 6_15.sh
1
2
3
[root@adminset 06]# cat 6_15.sh
[ -f /etc ] || {
echo 1
echo 2
echo 3
}
[root@adminset 06]# sh 6_15.sh
1
2
3
如果上述腳本寫在一行里面,那么里面的每個命令都需要用分號結尾,示例如下所示:
[root@adminset 06]# [ -f /etc/services ] && { echo "I am luoahong"; echo "I am linuxer"; }
I am luoahong
I am linuxer
提示:本例的兩種用法都很簡潔,但是不如if條件容易理解,因此請讀者根據自身情況選擇使用,更多幫助請man test查詢
字符串測試表達式
字符串測試操作符
范例:字符串條件表達式測試實踐
[root@adminset 06]# [ -n "abc" ] && echo 1 || echo 0 1 [root@adminset 06]# test -n "" && echo 1 || echo 0 0 [root@adminset 06]# var="luoahong" [root@adminset 06]# [ -n "$var" ] && echo 1 || echo 0 1 [root@adminset 06]# [ -n $var ] && echo 1 || echo 0 1 [root@adminset 06]# var="luoahong1" [root@adminset 06]# [ -z $var ] && echo 1 || echo 0 0 [root@adminset 06]# [ "abc" = "abd" ] && echo 1 || echo 0 0 [root@adminset 06]# [ "$var" = "luoahong1" ] && echo 1 || echo 0 1 [root@adminset 06]# [ "$var" == "luoahong1" ] && echo 1 || echo 0 1 [root@adminset 06]# [ "$var" != "luoahong1" ] && echo 1 || echo 0 0
字符串測試生產案例
范例:有關雙引號和等號兩端空格的生產系統標准
[root@adminset 06]# sed -n '30,31p' /etc/init.d/network
#check that networking is up
[ "${NETWORKING}" = "no" ] && exit 6
#字符串變量和字符串都加了雙引號,比較符號"="兩端也都有空格
范例:系統腳本/etc/init.d/nfs字符串測試的應用示例
[root@adminset 06]# sed -n '65,80p' /etc/init.d/nfs [ -z "$MOUNTD_NFS_V2" ] && MOUNTD_NFS_V2=default #-z的應用,如果變量MOUNTD_NFS_V2的長度為0則賦值default [ -z "$MOUNTD_NFS_V3" ] && MOUNTD_NFS_V3=default #-z的應用,如果變量MOUNTD_NFS_V3的長度為0則賦值default # Number of servers to be started by default [ -z "$RPCNFSDCOUNT" ] && RPCNFSDCOUNT=8 # Start daemons. [ -x /usr/sbin/rpc.svcgssd ] && /sbin/service rpcsvcgssd start # Set the ports lockd should listen on if [ -n "$LOCKD_TCPPORT" -o -n "$LOCKD_UDPPORT" ]; then #-n的應用 [ -x /sbin/modprobe ] && /sbin/modprobe lockd $LOCKDARG [ -n "$LOCKD_TCPPORT" ] && \ /sbin/sysctl -w fs.nfs.nlm_tcpport=$LOCKD_TCPPORT >/dev/null 2>&1 [ -n "$LOCKD_UDPPORT" ] && \ /sbin/sysctl -w fs.nfs.nlm_udpport=$LOCKD_UDPPORT >/dev/null 2>&1 fi
整數變量測試示例
范例:通過[]實現整數條件測試
[root@adminset 06]# a1=98;a2=99 [root@adminset 06]# [ $a1 -eq $a2 ] && echo 1 ||echo 0 0 [root@adminset 06]# [ $a1 -gt $a2 ] && echo 1 ||echo 0 0 [root@adminset 06]# [ $a1 -lt $a2 ] && echo 1 ||echo 0 1
范例:利用[[]]和(())實現直接通過常規數學運算符進行比較
[root@adminset 06]# [[ $a1 > $a2 ]] && echo 1 ||echo 0 0 [root@adminset 06]# [[ $a1 < $a2 ]] && echo 1 ||echo 0 1 [root@adminset 06]# (($a1>=$a2)) && echo 1|| echo 0 0 [root@adminset 06]# (($a1<=$a2)) && echo 1|| echo 0 1
范例:系統腳本中使用整數比較的案例
[root@adminset ~]#grep -w "\-eq" /etc/init.d/nfs [ $RETVAL -eq 0 ] && RETVAL=$rval #過濾出相等(-eq)的例子 [ $RETVAL -eq 0 ] && RETVAL=$rval #使用[],且兩邊都要有一個空格 [ $RETVAL -eq 0 ] && RETVAL=$rval #使用"-eq" 的比較操作符的寫法 [ $RETVAL -eq 0 ] && RETVAL=$rval [ $RETVAL -eq 0 ] && RETVAL=$rval [root@adminset ~]#grep -w "\-gt" /etc/init.d/nfs #過濾出大於(-gt)的例子 if [ $cnt -gt 0 ]; then
邏輯操作符實踐示例
范例:[]里的邏輯操作配合文件測試表達式使用的示例
[root@adminset 06]# f1=/etc/rc.local;f2=/etc/services [root@adminset 06]# echo -ne "$f1 $f2\n" /etc/rc.local /etc/services [root@adminset 06]# [ -f "$f1" -a -f "$f2" ] && echo 1 || echo 0 1 [root@adminset 06]# [ -f "$f1" -o -f "$f222" ] && echo 1 || echo 0 1 [root@adminset 06]# [ -f "$f111" -o -f "$f222" ] && echo 1 || echo 0 0 [root@adminset 06]# [ -f "$f1" && -f "$f2" ] && echo 1 || echo 0 -bash: [: missing `]' 0 #這是錯誤的語法,[]中不能用&&|| [root@adminset 06]# [ -f "$f1" ] && [ -f "$f2" ] && echo 1 || echo 0 1 #如果在[]中使用&&,則這樣用
范例:[[]]里邏輯操作符配合字符串的條件表達式的測試示例
[root@adminset 06]# a="luoahong";b="tyx" [root@adminset 06]# echo -ne "$a $b\n" luoahong tyx [root@adminset 06]# [[ ! -n " $a" && "$a" = "$b"]] && echo 1 || echo 0 -bash: conditional binary operator expected -bash: syntax error near `1' [root@adminset 06]# [[ ! -n "$a" && "$a" = "$b"]] && echo 1 || echo 0 -bash: conditional binary operator expected -bash: syntax error near `1' [root@adminset 06]# [[ ! -n "$a" && "$a" = "$b" ]] && echo 1 || echo 0 0 [root@adminset 06]# [[ -z "$a" || "$a" != "$b" ]] && echo 1 || echo 0 1 [root@adminset 06]# [root@adminset 06]# [[ -z "$a" -o "$a" != "$b" ]] && echo 1 || echo 0 -bash: syntax error in conditional expression -bash: syntax error near `-o'
范例:(())里邏輯操作符符合整數的條件表達式測試示例
[root@adminset 06]# m=21;n=38 [root@adminset 06]# ((m>20&&n>30)) && echo 1 || echo 0 1 [root@adminset 06]# ((m>20||n>30)) && echo 1 || echo 0 1 [root@adminset 06]# ((m<20||n<30)) && echo 1 || echo 0 0 [root@adminset 06]# ((m<20 -a n<30)) && echo 1 || echo 0 -bash: ((: m<20 -a n<30: syntax error in expression (error token is "n<30") 0 #內部用-a或-o也會報語法錯誤
范例:使用多個[]號,並通過與或非進行混合測試
[root@adminset 06]# m=21;n=38 [root@adminset 06]# [ $m =gt 20 -a $n -lt 30 ] && echo 1 || echo 0 -bash: [: too many arguments 0 [root@adminset 06]# [ $m gt 20 -a $n -lt 30 ] && echo 1 || echo 0 -bash: [: too many arguments 0 [root@adminset 06]# [ $m -gt 20 -a $n -lt 30 ] && echo 1 || echo 0 0 [root@adminset 06]# [ $m -gt 20 ] || [ $n -lt 30 ] echo 1 || echo 0 [root@adminset 06]# [ $m -gt 20 ] || [ $n -lt 30 ] && echo 1 || echo 0 1 #多個[]號之間用&&或||鏈接
范例:NFS系統啟動腳本中有關[]與或非判斷的使用案例
[root@adminset~]#egrep -wn "\-a|\-o" /etc/init.d/nfs
75: if [ -n "$LOCKD_TCPPORT" -o -n "$LOCKD_UDPPORT" ]; then
87: [ "$NFSD_MODULE" != "noload" -a -x /sbin/modprobe ] && {
102: if [ -n "$RQUOTAD" -a "$RQUOTAD" != "no" ]; then
170: if [ -n "$RQUOTAD" -a "$RQUOTAD" != "no" ]; then
209: if [ -n "$RQUOTAD" -a "$RQUOTAD" != "no" ]; then
229: if [ $MOUNTD = 1 -o $NFSD = 1 ] ; then
范例:系統啟動腳本中有關[[]]的用法和與或非的使用案例
在操作系統中,[[]]的用法不是很多,並且大多數情況都用於通配符匹配的場景,這里不的不通過大海撈針的
方法(遍歷/etc/init.d/下的所有腳本)來幫助大家查找[[]]的用法:
[root@69 ~]# for n in `ls /etc/init.d/*`;do egrep -wn "\[\[ " $n&&echo $n;done 119: if [[ "$dst" == /dev/mapper* ]] \ /etc/init.d/halt 68: if [[ $? = 0 ]]; then /etc/init.d/httpd 641: if [[ -n "$_target" ]]; then 656: if [[ "$_rmnt" == "$_mnt" ]] || ! is_dump_target_configured; then /etc/init.d/kdump 50: if [[ $route == *" via "* ]] ; then 75: if ! [[ "$SYSLOGADDR" =~ $IPv4_regex ]] && ! [[ "$SYSLOGADDR" =~ $IPv6_regex ]];then 80: if [[ $? -eq 2 ]]; then 84: if [[ $? -ne 0 ]]; then /etc/init.d/netconsole 167: if [[ "$rootfs" == nfs* || "$rootopts" =~ _r?netdev ]] ; then /etc/init.d/network
提示:可見[]中使用-a或-o更常見,[[]]中使用&&或||不常見,使用&&或||鏈接兩個[]的多表達式判斷也不常見
