if/else
if/else 的語法如下:
if condition
then
statements
[elif condition
then statements...]
[else
statements]
fi
Exit Status
與其他程式語言(C、C++、Pascal....等等)不同的地方,在 condition 的部分,其他的程式語言是以 condition 為 True or False 來決定要執行哪一段程式;但在 bash 中卻不是如此!
在 bash 中,就必須按照 Linux 的運作方式來進行處理,因此 condition 是否成立取決於 command 的 exit status。
而在 Linux 的所有指令,不論是由何種程式語言開發,執行完後都會回傳一個整數值給呼叫此程式的 process,此整數值即稱為 exit status;一般來說,「0」代表程式執行成功,而「1~255」則代表程式執行失敗。
有了 exit status 的概念後,if/else 的語法就可以修改如下:
if command ran successfully
then
normal processing
else
error processing
fi
Return
這邊要探討的是一般程式語言都有提供的 return 功能,其實說穿了,return N 即是 exit N(Exit Status 為N),不過比較不一樣的是,return 僅能用於 function 中,且要執行含有 function 的 shell script,必須透過 source 的方式來執行才有效。
總而言之,在 function 中使用 return 就跟在其他程式語言的方式差不多。
同時使用多個 Exit Status
或許有人會覺得,如果條件判斷中需要同時判斷兩個條件以上,要如何作呢? 在 bash 中當然也辦的到,就像其他程式語言一樣,bash 也可以針對判斷條件進行 &&(AND) 或是 ||(OR) 運算,來決定是否執行特定程式,以下用個簡單的範例說明:
filename=$1
word1=$2
word2=$3
if grep $word1 $filename || grep $word2 $filename
then
echo "$word1 or $word2 is in $filename."
fi
各種狀況的判斷
當然除了靠 Exit Status 外,還有許多不同的情況會發生,例如:字串比對、檔案屬性的檢查、數字比較....等等,以下逐一來進行介紹各種比對方式。
字串的比對:
Operator | 成立條件 |
str1 = str2 | 這不多解釋了.... |
str1 != str2 | 這不多解釋了.... |
str1 < str2 | 這不多解釋了.... |
str1 > str2 | 這不多解釋了.... |
-n str1 | 當 str1 不為 null 時 |
-z str1 | 當 str1 為 null 時(長度為 0) |
檔案屬性:
Operator | 成立條件 |
-a file | 檔案存在 |
-d file | 檔案存在,並且是個目錄 |
-e file | 檔案存在 |
-f file | 檔案存在,且為一般檔案(非目錄或其他特殊型態) |
-r file | 目前的使用者有讀取檔案的權限 |
-s file | 檔案存在且內容非空白 |
-w file | 目前的使用者有寫入檔案的權限 |
-x file | 目前的使用者有執行檔案(or 進入目錄)的權限 |
-N file | 檔案自從上一次被讀取後,有被修改過 |
-O file | 檔案的 owner 為目前的使用者 |
-G file | 檔案的 group 為目前使用者所屬之 group |
file1 -nt file2 | file1 比 file2 的日期新 |
file1 -ot file2 | file1 比 file2 的日期舊 |
如果使用上面的判斷時,最好加上「中括號」,變成類似以下的格式:
if [ condition ] && [ condition ]; then當然也可以跟 Exit Status 結合,就會變成類似以下的格式:
if command && [ condition ]; then以下來段簡單的程式(節錄自書):
當然,兩兩比較一定會有數字的比對,以下介紹數字比較的方式:# 檢查檔案是否不存在
if [ ! -e "$1" ]; then
echo "file $1 does not exist."
exit 1
fi
# 檢查是否為目錄
if [ -d "$1" ]; then
echo -n "$1 is a directory that you may "
if [ ! -x "$1" ]; then
echo -n "not "
fi
echo "search."
elif [ -f "$1" ]; then # 檢查是否為檔案
echo "$1 is a regular file."
else # 檢查是否為特殊型態的檔案
echo "$1 is a special type of file."
fi
# 檢查目前使用者是否為 owner
if [ -O "$1" ]; then
echo 'you own the file.'
else
echo 'you do not own the file.'
fi
# 檢查是否有讀取檔案的權限
if [ -r "$1" ]; then
echo 'you have read permission on the file.'
fi
# 檢查是否有寫入檔案的權限
if [ -w "$1" ]; then
echo 'you have write permission on the file.'
fi
# 檢查第一個參數是否有執行的權限,且非目錄
if [ -x "$1" -a ! -d "$1" ]; then
echo 'you have execute permission on the file.'
fi
Keyword | 效果 |
-lt | Less than (小於) |
-le | Less then or equal (小於或等於) |
-eq | Equal (等於) |
-ge | Greater than or equal (大於或等於) |
-gt | Greater than (大於) |
-ne | Not equal (不等於) |
for
for loop 在 bash 中當然也是不可欠缺的一員大將啦! 只是跟其他程式語言不同的地方,他並非以「數字」的方式直接指定 for loop 的程式要執行的次數,而是以一個串列的值(例如:1 3 4 6 8)去執行,有幾個值就執行幾次,因此格式大概如下:
for name [in list ]其實說穿了,使用方式就跟其他程式語言中的 for each 是差不多相同的,以下結合 if/else 判斷來個範例程式:
do
statements that can use $name...
done
#!/bin/bash
IFS=":"
for dir in $PATH
do
if [ -z "$dir" ]; then
dir="."
fi
if ! [ -e "$dir" ]; then
echo "${dir} doesn't exist"
elif ! [ -d "${dir}" ]; then
echo "${dir} diesn't a directory"
else
ls -ld $dir
fi
done
另外再舉個例子,將 function、for、if/else 通通結合進來,下面這個程式的目的是以 recursive 的方式將參數中目錄底下的所有目錄列出,以下是程式內容:
有興趣知道輸出結果的,可以 copy 回去自己試試看。echoDir() {
chrTab="${chrTab}t"
cd $1
for eachFilePath in $(ls)
do
if [ -d $eachFilePath ]; then
echo -e ${chrTab}${eachFilePath}
echoDir $eachFilePath
fi
done
cd ..
chrTab=${chrTab%'t'}
}
filePath=$1
chrTab=""
if [ -d $1 ]; then
cd $1
for eachFilePath in $(ls)
do
if [ -d $eachFilePath ]; then
echo $eachFilePath
echoDir $eachFilePath
fi
done
cd ..
fi
case
case 在 bash 中的用法其實就是跟 C、Java 等程式語言中的 switch case 差不多,以下是使用語法:
case expression in以下用個簡單程式來說明:
pattern1 )
statements ;;
pattern2 )
statements ;;
...
esac
for filename in "$@"; do
case $filename in
*.jpg | *.png ) echo "may be jpg or png" ;;
*.tga ) echo "tga" ;;
*.xpm ) echo "xpm" ;;
* ) echo "can not identified file type."
esac
done
select
這個部分就跟一般的程式語言很不一樣了! 而且僅在 bash 1.14 版以後才有支援喔! 透過 select,可以很容易的產生出選單,以下是使用 select 的語法:
select name [in list ]透過 select 語法,可以將 list 中的內容變成一個個的數字選項供使用者選擇,並且有兩個變數需要注意到,分別是 $name 以及 $REPLY;其中 $name 變數的值為選項的內容,而 $REPLY 的值則是選項所代表的數字。
do
statements that can use $name...
done
當使用者輸入某選項的數字時,$name 與 $REPLY 就會存入相對應的值,但若是輸入一個非選項內的數字,則兩個變數的值都會變成 null,因此可以透過檢查 $name 變數值是否為 null 來判斷使用者有無輸入合法的選項。
以下用一個簡單的小程式來作範例:
至於 select 要如何應用在許許多多的管理工作上,就需要管理者發揮創意了!#!/bin/bash
# 指定分隔 $PATH 的字元
IFS=":"
# 變數 PS3 儲存使用 select 時提示使用者的字串
PS3="which path you want to use? "
select mySelect in $PATH;
do
if [ $mySelect ]; then
echo "mySelect = ${mySelect}"
echo "REPLY = ${REPLY}"
else
echo "no such option!"
# 透過關鍵字「break」就可離開了!
break;
fi
done
# 以下是執行結果:
1) /usr/kerberos/sbin 4) /usr/local/bin 7) /usr/sbin
2) /usr/kerberos/bin 5) /sbin 8) /usr/bin
3) /usr/local/sbin 6) /bin 9) /root/bin
which path you want to use? 1
mySelect = /usr/kerberos/sbin
REPLY = 1
which path you want to use? 5
mySelect = /sbin
REPLY = 5
which path you want to use? 10
no such option!
while & until
在 while 與 until 的部分,也是跟一般程式語言中的用法差不多,以下分別介紹 while 與 until 的語法:
while
while condition dountil
statements... done
until command ; do statements... done其實說穿了,while 與 until 不過就是一體兩面的用法而已,差別僅在於 while 判斷條件是否為 true,until 判斷條件是否為 false。
以下用兩段程式來說明,以下兩段程式的作用是相同的,只是分別以 while 與 until 來撰寫:
until [ cp $1 $2 ];
do
echo 'Attempt to cpoy failed. waiting...'
sleep 5
done
這裡僅是簡單用法的介紹,其他就靠大家發揮了!while [ ! cp $1 $2 ];
do
echo 'Attempt to cpoy failed. waiting...'
sleep 5
done
沒有留言:
張貼留言