第十二章:使用結(jié)構(gòu)化命令
本章內(nèi)容
使用if-then語句
嵌套if語句
test命令
復(fù)合條件測(cè)試
使用雙方括號(hào)和雙括號(hào)
case命令
12.1 使用if-then語句
語句格式:
if command
then
command
fi
或
if command; then
command
fi
語句說明:bash shell的if語句會(huì)運(yùn)行if后面的那個(gè)命令滚局,如果該命令的退出狀態(tài)碼是0(該命令執(zhí)行成功)燕锥,則位于then部分的命令就回被執(zhí)行。如果不是0毙沾,則不執(zhí)行then部分的命令,繼續(xù)執(zhí)行腳本中的下一個(gè)命令宠页。fi語句表示if-then語句到此結(jié)束左胞。
編寫test1.sh腳本
#!/bin/bash
# testing the if statement
if pwd
then
echo It worked
fi
編寫test2.sh腳本
#!/bin/bash
# testing a bad command
if IamNotaCommand
then
echo "It worked"
fi
echo "We are outside the if statement"
編寫test3.sh腳本
#!/bin/bash
if grep $testuser /etc/passwd
then
echo "This is my first command"
echo "This is my second command"
echo "I can even put in other commands besides echo:"
ls -a /home/$testuser/.b*
fi
12.2 if-then-else語句
語句格式
if command
then
command
else
command
fi
語句說明:當(dāng)if語句中的命令返回退出狀態(tài)碼為0時(shí),then部分中的命令會(huì)被執(zhí)行举户;當(dāng)狀態(tài)碼不為0時(shí)烤宙,else部分中的命令會(huì)被執(zhí)行。
編寫test4.sh腳本
#!/bin/bash
# testing multiple commands in the then section
testuser=nosuchuser
if grep $testuser /etc/passwd
then
echo "This is my first command"
echo "This is my second command"
echo "I can even put in other commands besides echo:"
ls -a /home/$testuser/.b*
else
echo "The user $testuser does not exist on this system."
fi
12.3 嵌套if
要檢查/etc/passwd文件中是否存在某個(gè)用戶以及該用戶的目錄是否尚在俭嘁,可以使用嵌套的if-then語句躺枕。嵌套的if-then語句位于主if-then-else語句的else代碼塊中。
語句格式
if command1
then
commands
elif command2
then
more commands
else
moreandmore commands
fi
語句說明:先執(zhí)行command1供填,返回狀態(tài)碼為0時(shí)拐云,執(zhí)行commands,從elif到fi之間的命令則跳過捕虽。當(dāng)command1返回狀態(tài)碼不為0時(shí)慨丐,則執(zhí)行command2,command2的返回狀態(tài)碼為0泄私,則執(zhí)行more commands房揭;不為0,則執(zhí)行moreandmore commands晌端。
編寫test5.sh腳本
#!/bin/bash
# testing nested ifs - use elif
testuser=nosuchuser
if grep $testuser /etc/passwd
then
echo "The user $testuser exists on this system."
elif ls -d /home/$testuser
then
echo "The user $testuser dose not exist on this system."
echo "However,$testuser has a directory"
else
echo "The user $testuser dose not exist on this system."
echo "And,$testuser dose not have a directory"
fi
竅門:在elif語句中捅暴,緊跟其后的else語句屬于elif代碼塊。它們并不屬于之前的if-then代碼塊咧纠。
可以將多個(gè)elif語句串起來
if command1
then
command set 1
elif command2
then
command set 2
elif command3
then
command set 3
elif command4
then
command set 5
fi
12.4 test命令
命令格式:test condition
命令說明:如果test命令中列出的條件成立蓬痒,test命令就回返回0,否則返回非零的狀態(tài)碼漆羔,這樣就可以結(jié)合if-then語句使用梧奢。
語句格式
if test condition
then
commands
fi
語句說明:如果test命令的condition部分為空時(shí)狱掂,它會(huì)返回非零的退出狀態(tài)碼。
語句格式
if [ condition ]
then
commands
fi
語句說明:bash shell提供的另一種測(cè)試方法亲轨,第一個(gè)方括號(hào)之后和第二個(gè)方括號(hào)之前必須加一個(gè)空格趋惨。
test命令可以判斷三類條件
數(shù)值比較
字符串比較
文件比較
12.4.1 數(shù)值比較
test命令的數(shù)值比較功能
n1 -eq n2:檢查n1是否等于n2
n1 -gen2:檢查n1是否大于或等于n2
n1 -gt n2:檢查n1是否大于n2
n1 -le n2:檢查n1是否小于或等于n2
n1 -lt n2:檢查n1是否小于n2
n1 -ne n2:檢查n1是否不等于n2
編寫numberic_test.sh腳本
#!/bin/bash
value1=10
value2=11
#
if [ $value1 -gt 5 ]
then
echo "The test value $value1 is greater then 5"
fi
#
if [ $value1 -eq $value2 ]
then
echo "The values are equal"
else
echo "The values are different"
fi
bash shell只能處理整數(shù)。如果只是通過echo來顯示浮點(diǎn)數(shù)惦蚊,則沒問題器虾;如果用于數(shù)值比較,則會(huì)出錯(cuò)蹦锋。
編寫floating_point_test.sh腳本
#!/bin/bash
#
value1=5.555
#
echo "The test value is $value1"
#
if [ $value1 -gt 5 ]
then
echo "The test value $value1 is greater then 5"
fi
12.4.2 字符串比較
字符串比較測(cè)試
str1 = str2:檢查str1是否和str2相同
str1 != str2:檢查str1是否和str2不同
str1 < str2:檢查str1是否比str2姓咨场(使用時(shí)大于符號(hào)注意轉(zhuǎn)義)
str1 > str2:檢查str1是否比str2大(使用時(shí)小于符號(hào)注意轉(zhuǎn)義)
-n str2:檢查str1的長(zhǎng)度是否非0
-z str2:檢查str1的長(zhǎng)度是否為0
1.字符串相等性
編寫test7.sh腳本
#!/bin/bash
# testing string equality
testuser=rich
#
if [ $USER = $testuser ]
then
echo "Welcome $testuser"
else
echo "This is not $testuser"
fi
編寫test8.sh腳本
#!/bin/bash
# testing string equality
testuser=rich
#
if [ $USER != $testuser ]
then
echo "This is not $testuser"
else
echo "Welcome $testuser"
fi
2.字符串順序
編寫test9.sh腳本
#!/bin/bash
# mis-using string comparisons
#
val1=baseball
val2=hockey
#
if [ $val1 \> $val2 ]
then
echo "$val1 is greater than $val2"
else
echo "$val1 is less than $val2"
fi
注意:在進(jìn)行字符串比較時(shí),使用的是標(biāo)準(zhǔn)的ASCII順序莉掂,根據(jù)每個(gè)字符的ASCII數(shù)值來決定排序結(jié)果葛圃,大寫字母被認(rèn)為是小于小寫字母的。但sort命令恰好相反憎妙。
說明:test命令和測(cè)試表達(dá)式使用標(biāo)準(zhǔn)的數(shù)學(xué)比較符號(hào)來表示字符串比較装悲,而用文本代碼(如:-eq,-ge等)來表示數(shù)值比較尚氛。這個(gè)細(xì)微的特性被很多程序員理解反了。如果你對(duì)數(shù)值使用了數(shù)據(jù)運(yùn)算符洞渤,shell會(huì)將它們當(dāng)成字符串值阅嘶,可能無法得到正確的結(jié)果。
3.字符串大小
編寫test10.sh腳本
#!/bin/bash
# testing string length
val1=testing
val2=''
#
if [ -n $val1 ]
then
echo "The string '$val1' is not empty"
else
echo "The string '$val1' is empty"
fi
#
if [ -z $val2 ]
then
echo "The string '$val2' is empty"
else
echo "The string '$val2' is not empty"
fi
#
if [ -z $val3 ]
then
echo "The string '$val3' is empty"
else
echo "The string '$val3' is not empty"
fi
敲門:空的和未初始化的變量會(huì)對(duì)shell腳本測(cè)試造成災(zāi)難性的影響载迄。如果不是很確定一個(gè)變量的內(nèi)容讯柔,最好在將其用于數(shù)值或字符串比較之前先通過-n或-z來測(cè)試一下變量是否含有值。
12.4.3 文件比較
test命令的文件比較功能
-d file:檢查file是否存在并是一個(gè)目錄
-e file:檢查file是否存在
-f file:檢查file是否存在并是一個(gè)文件
-r file:檢查file是否存在并可讀
-s file:檢查file是否存在并非空
-w file:檢查file是否存在并可寫
-x file:檢查file是否存在并可執(zhí)行
-O file:檢查file是否存在并屬當(dāng)前用戶所有
-G file:檢查file是否存在并且默認(rèn)組與當(dāng)前用戶相同
file1 -nt file2:檢查file1是否比file2新
file1 -ot file2:檢查file1是否比file2舊
1.檢查目錄
-d測(cè)試會(huì)檢查指定的目錄是否存在于系統(tǒng)中护昧。如果你打算將文件寫入目錄或是準(zhǔn)備切換到某個(gè)目錄中魂迄,先進(jìn)行測(cè)試總是件好事情
編寫test11.sh腳本
#!/bin/bash
# Look before you leap
#
jump_directory=/home/zc
#
if [ -d $jump_directory ]
then
echo "The $jump_directory directory exists"
cd $jump_directory
ls
else
echo "The $jump_directory directory dose not exist"
fi
2.檢查對(duì)象是否存在
-e比較允許你的腳本代碼在使用文件或目錄前先檢查它們是否存在
編寫test12.sh腳本
#!/bin/bash
# Check if either a directory or file exists
#
location=$HOME
file_name="sentinel"
#
if [ -e $location ]
then #Directory does exist
echo "OK on the $location directory."
echo "Now checking on the file, $file_name."
#
if [ -e $location/$file_name ]
then #File does exist
echo "OK on the filename"
echo "Updating Current Date..."
date >> $location/$file_name
#
else #File does not exist
echo "File does not exist"
echo "Nothing to update"
fi
#
else #Directory does not exist
echo "The $location directory does not exist."
echo "Nothing to update"
fi
3.檢查文件
-e比較可用于文件和目錄。要確定指定對(duì)象為文件惋耙,必須用-f比較
編寫test12.sh
#!/bin/bash
# check if either a directory or file exists
#
item_name=$HOME
echo
echo "The item being checked: $item_name"
echo
#
if [ -e $item_name ]
then #Item does exist
echo "The item, $item_name, does exist."
echo "But is it a file?"
echo
#
if [ -f $item_name ]
then #Item is a file
echo "Yes, $item_name is a file."
#
else #Item is not a file
echo "No, $item_name is not a file."
fi
#
else #Item does not exist
echo "The item, $item_name, does not exist."
echo "Nothing to update"
fi
4.檢查是否可讀
在嘗試從文件中讀取數(shù)據(jù)之前捣炬,最好先測(cè)試一下文件是否可讀,可以使用-r比較測(cè)試
編寫test14.sh腳本
#!/bin/bash
# testing if you can read a file
pwfile=/etc/shadow
#
# first, test if the file exists, and is a file
if [ -f $pwfile ]
then
# now test if you can read it
if [ -r $pwfile ]
then
tail $pwfile
else
echo "Sorry, I am unable to read the $pwfile file"
fi
else
echo "Sorry, the file $pwfile does not exist"
fi
5.檢查空文件
使用-s比較來檢查文件是否為空绽榛,當(dāng)-s比較成功時(shí)湿酸,說明文件中有數(shù)據(jù)。
編寫test15.sh腳本
#!/bin/bash
# Testing if a file is empty
#
file_name=$HOME/sentinel
#
if [ -f $file_name ]
then
if [-s $file_name ]
then
echo "The $file_name file exists and has data in it."
echo "Will not remove this file."
else
echo "The $file_name file exists,but is empty."
echo "Deleting empty file..."
rm $file_name
fi
else
echo "File,$file_name,does not exist."
fi
6.檢查是否可寫
使用-w比較進(jìn)行判斷你對(duì)文件是否有可寫權(quán)限
編寫test16.sh腳本
#!/bin/bash
# check if a file is writable.
#
item_name=$HOME/sentinel
echo
echo "The item being checked: $item_name"
echo
#
if [ -e $item_name ]
then #Item does exist
echo "The item, $item_name, does exist."
echo "But is it a file?"
echo
#
if [ -f $item_name ]
then #Item is a file
echo "Yes, $item_name is a file."
echo "But is it writable?"
echo
#
if [ -w $item_name ]
then #Item is writable
echo "Writing current time to $item_name"
date +$H$M >> $item_name
#
else #Item is not writable
echo "Unable to write to $item_name"
fi
#
else #Item is not a file
echo "No, $item_name is not a file."
fi
#
else #Item does not exist
echo "The item, $item_name, does not exist."
echo "Nothing to update"
fi
7.檢查文件是否可以執(zhí)行
使用-x比較判斷特定文件是否有執(zhí)行權(quán)限
編寫test17.sh腳本
#!/bin/bash
# testing file execution
#
if [ -x test16.sh ]
then
echo "You can run the script:"
./test16.sh
else
echo "Sorry, you are unable to execute the script"
fi
8.檢查所屬關(guān)系
使用-O比較測(cè)試當(dāng)前用戶是否是文件的屬主
編寫test18.sh腳本
#!/bin/bash
# eheck file ownership
#
if [ -O /etc/passwd ]
then
echo "You are the owner of the /etc/passwd file"
else
echo "Sorry, you are not the owner of the /etc/passwd file"
fi
9.檢查默認(rèn)屬組關(guān)系
使用-G比較檢查文件的默認(rèn)組灭美,如果它匹配了用戶的默認(rèn)組推溃,則測(cè)試成功。注:-G比較只會(huì)檢查默認(rèn)組而非用戶所屬的所有組届腐。
編寫test19.sh腳本
#!/bin/bash
# check file group test
#
if [ -G $HOME/testing ]
then
echo "You are in the same group as the file"
else
echo "The file is not owned by you group"
fi
10.檢查文件日期
使用-nt比較判斷一個(gè)文件是否比另一個(gè)文件新铁坎。如果文件較新蜂奸,則文件的創(chuàng)建日期更近。
使用-ot比較判斷一個(gè)文件是否比另一個(gè)文件舊硬萍。如果文件較舊扩所,則文件的創(chuàng)建日期更早。
編寫test20.sh腳本
#!/bin/bash
# testing file dates
#
if [ test19.sh -nt test18.sh ]
then
echo "The test19 file is newer than test18"
else
echo "The test18 file is newer than test19"
fi
if [ test17.sh -ot test19.sh ]
then
echo "The test17 file is older than the test19 file"
fi
編寫test21.sh腳本
#!/bin/bash
# testing file dates
#
if [ badfile1 -nt badfile2 ]
then
echo "The badfile1 file is newer than badfile2"
else
echo "The badfile2 file is newer than badfile1"
fi
注意:這些命令都沒有檢查文件是否存在襟铭,在使用這些命令之前碌奉,必須先確認(rèn)文件是存在的
12.5 復(fù)合條件測(cè)試
if-then語句允許使用布爾邏輯來組合測(cè)試,格式如下
[ condition1 ] && [ condition2 ]
[ condition1 ] || [ condition2 ]
竅門:布爾邏輯是一種能夠?qū)⒖赡艿姆祷刂岛?jiǎn)化為TRUE或FALSE的方法
編寫test22.sh腳本
#!/bin/bash
# testing compound comparisons
#
if [ -d $HOME ] && [ -w $HOME/testing ]
then
echo "The file exists and you can write to it"
else
echo "I connot write to the file"
fi
12.6 if-then的高級(jí)特性
12.6.1 使用雙括號(hào)
命令格式:(( expression ))
命令說明:使用雙括號(hào)可以在比較過程中使用高級(jí)數(shù)據(jù)表達(dá)式
雙括號(hào)命令符號(hào)
val++:后自增
val--:后自減
++val:先自增
--val:先自減
!:邏輯求反
~:位求反
**:冪運(yùn)算
<<:左位移
>>:右位移
&:位布爾與
|:位布爾或
&&:邏輯與
||:邏輯或
編寫test23.sh腳本
#!/bin/bash
# using double parenthesis
#
var1=10
#
if (( $val1 ** 2 > 90 ))
then
(( val2 = $val1 ** 2 ))
echo "The square of $val1 is $val2"
fi
12.6.2 使用雙方括號(hào)
命令格式:[[ expression ]]
命令說明:在單方括號(hào)的基礎(chǔ)上寒砖,增加了模式匹配
命令注意:并不是所有的shell都支持雙方括號(hào)
編寫test24.sh腳本
#!/bin/bash
# using pattern matching
#
if [[ $USER == z* ]]
then
echo "Hello $USER"
else
echo "Sorry,I do not know you"
fi
12.7 case命令
編寫test25.sh腳本
#!/bin/bash
# looking for a possible value
#
if [ $USER = "zc" ]
then
echo "Welcome $USER"
echo "Please enjoy your visit"
elif [ $USER = "barbara" ]
then
echo "Welcome $USER"
echo "Please enjoy your visit"
elif [ $USER = "testing" ]
then
echo "Special testing account"
elif [ $USER = "jessica" ]
then
echo "Do not forget to logout when you're done"
else
echo "Sorry, you are not allowd here"
fi
命令格式:
case variable in
pattern1 | pattern2) commands1;;
pattern3) commands2;;
*) commands3;;
esac
命令說明:case命令會(huì)將指定的變量與不同模式進(jìn)行比較
編寫test26.sh腳本
#!/bin/bash
# using the case command
#
case $USER in
rich | barbara)
echo "Welcome, $USER"
echo "Please enjoy your visit";;
testing)
echo "Special testing account";;
jessica)
echo "Do not forget to log off when you're done";;
*)
echo "Sorry, you are not allowed here";;
esac
12.8 小結(jié)
結(jié)構(gòu)化命令可以改變shell腳本的正常執(zhí)行流赐劣。最基本的結(jié)構(gòu)化命令是if-then語句。該語句可以根據(jù)一個(gè)執(zhí)行一個(gè)命令的結(jié)果來執(zhí)行其他命令哩都。本章介紹了if-then魁兼、if-then-else、elif漠嵌、case語句咐汞。