昨天介紹了套件管理軟體以及圖形化使用者界面的安裝,也是指令介紹的最後一篇文章。學習了這麼多指令後,如果能靈活運用,使用 Linux 來做一些基礎的軟體開發我想應該都還撐的住!
今天是機派X系列文章的第八天。
本篇將介紹 Bash 的變數操作、條件判斷與流程控制。學習過這些東西後,就能用 Bash 將數條指令組合起來依序執行,變成有用的小程式。
本篇大綱:
也許你會疑惑,為什麼要學習這些,這些很明顯都是在學程式啊,但是我的專案又不用 Bash 開發!為何要學這些?
原因很簡單:如果以 Linux 做為開發平台,學習 Bash 有助於你寫一些「小工具」,讓你在主要程式開發的過程中更方便。
我會在下一篇文章中用 Bash 寫一些實用的小程式,希望能解除大家的疑惑。
由於下一篇文章才會帶領大家開新檔案、撰寫腳本,所以建議將本篇與下一篇搭配著看。
首先,來介紹變數這個東西。
可以想像變數(Variable)就是一個盒子,用於儲存資料。撰寫程式時,常常會需要很多不同的「盒子」來儲存不同資料。每個變數(或說盒子)都有一個名稱,該名稱由寫程式的人定義,以便撰寫程式時調用,透過呼叫變數名稱就可以取得或變更其中的資料內容。
在 Bash 中設定變數可以使用 export 來完成,若要取用變數則要透過 $ 。
以下是 export 的語法,並請注意 = 左右兩邊不可有空格!
export NAME[=DATA]
例如:
export my_name='Kevin Huang'
在變數名稱前方加上 $ 就可以取得該變數的值:
echo "My name is $my_name !"
Note :
此時,單引號與雙引號的使用就會出現差異。如果使用單引號,具有特殊意義的字元(例如:$ 符號)不會被解析,因此會「如實呈現」顯示「My name is $my_name !」。如果使用雙引號,具有特殊意義的字元(例如:$ 符號)才會被解析,因此會顯示「My name is Kevin Huang !」。
接下來,你可以嘗試以下範例:
export name='Kevin'
export name='$name Huang'
echo "$name"
export name='Kevin'
export name="$name Huang"
echo "$name"
Note :
如果你有學過其他程式語言,你可以能會好奇:怎麼沒有介紹變數的資料型態(Data Type)呢?
Answer:因為 Bash 只有一種資料型態,就是字串(String),所以其實沒有必要特別介紹,畢竟對於沒有學過其他程式語言的新手來說,資料型態的概念比較陌生,Bash 這種特殊的資料型態不說也罷,說了之後搞不好概念更亂了。
可以使用 read 來讀取使用者輸入的資料,VARIABLE 則是儲存使用者輸入資料的變數名,-r 引數則是不解析輸入資料中的跳脫字元,-p 引數則是給使用者的提示文字。
每次執行 read 都是讀取一行,行中若有空白則會依照空白切割,並將切割出來的字串依序儲存在變數中。
read [-r] [-p PROMPT] VARIABLE......
舉例來說:
read -p 'Please input your name and address: ' name address
使用者輸入:
Bella Taipei, Taiwan
可以使用 echo 印出使用者輸入的文字:
echo "Hello $name. $address is a nice place."
有時候會需要針對資料內容做條件判斷,依照判斷的結果執行不同的指令。
舉例來說:請使用者輸入年齡,若輸入的年齡大於等於 18 歲就 ...... ,否則就 ...... 。
以下是如果 TEST 條件判斷為真(True),就會執行 Block 中的指令。
if [[ TEST ]]
then
# Block
fi
以下是如果 TEST 條件判斷為真(True),就會執行 Block 1 中的指令;
如果條件判斷為假(False),則會執行 Block 2 中的指令。
if [[ TEST ]]
then
# Block 1
else
# Block 2
fi
以下是如果 TEST1 條件判斷為真(True),就會執行 Block 1 中的指令,其餘測試則不再判斷;如果條件判斷為假(False),才會接續 TEST2 的判斷。
如果 TEST2 條件判斷為真(True),就會執行 Block 2 中的指令;如果條件判斷為假(False),就會直接執行 Block 3 的指令。
if [[ TEST1 ]]
then
# Block 1
elif [[ TEST2 ]]
then
# Block 2
else
# Block 3
fi
Note :
TEST 是要執行的測試(test),依照測試結果會返回真(True)或假(False)。
測試 | 測試說明 |
---|---|
!TEST | 反轉 TEST 的測試結果。 |
-z STRING | 判斷 STRING 是否為空字串。 |
-n STRING | 判斷 STRING 是否不為空字串。 |
STRING1 = STRING2 | 判斷 STRING1 是否與 STRING2 相同。 |
STRING1 != STRING2 | 判斷 STRING1 是否與 STRING2 不同。 |
STRING1 > STRING2 | 判斷 STRING1 的 ASCII 序列是否大於 STRING2。 |
STRING1 < STRING2 | 判斷 STRING1 的 ASCII 序列是否小於 STRING2。 |
INTEGER1 -eq INTEGER2 | 判斷 INTEGER1 是否等於 INTEGER2。 |
INTEGER1 -ne INTEGER2 | 判斷 INTEGER1 是否不等於 INTEGER2。 |
INTEGER1 -gt INTEGER2 | 判斷 INTEGER1 是否大於 INTEGER2。 |
INTEGER1 -lt INTEGER2 | 判斷 INTEGER1 是否小於 INTEGER2。 |
INTEGER1 -ge INTEGER2 | 判斷 INTEGER1 是否大於或等於 INTEGER2。 |
INTEGER1 -le INTEGER2 | 判斷 INTEGER1 是否小於或等於 INTEGER2。 |
TEST1 && TEST2 | 將 TEST1 與 TEST2 的測試結果做 AND 邏輯運算。 |
TEST1 || TEST2 | 將 TEST1 與 TEST2 的測試結果做 OR 邏輯運算。 |
-f PATH | 判斷 PATH 是否存在,而且是一個檔案。 |
-d PATH | 判斷 PATH 是否存在,而且是一個目錄。 |
-s PATH | 判斷 PATH 是否存在,而且檔案內容不為空。 |
-r PATH | 判斷 PATH 是否存在,而且當前使用者對該檔案具有讀取權限。 |
-w PATH | 判斷 PATH 是否存在,而且當前使用者對該檔案具有寫入權限。 |
-x PATH | 判斷 PATH 是否存在,而且當前使用者對該檔案具有執行權限。 |
舉幾個例子來看看吧:
read -p 'How old are you? ' age
if [[ $age -ge 18 ]]
then
echo 'Let us do something interesting ......'
fi
read -p 'How old are you? ' age
if [[ $age -ge 18 ]]
then
echo 'Let us do something interesting ......'
else
echo 'Go to the basement and sweep the floor!'
fi
read -p 'How many books on the shelf? ' numBook
if [[ $numBook -lt 0 ]]
then
echo '??????????????????????????????????'
elif [[ $numBook -eq 0 ]]
then
echo 'You can buy a book from www.books.com.tw .'
elif [[ $numBook -gt 10 ]]
then
echo 'You are a man or woman who likes to read!'
else
echo 'You can buy more books from www.books.com.tw .'
fi
有時候也會需要重複執行某些指令,因此會需要用到迴圈(loop)。
迴圈有很多種寫法,以下將一一舉例介紹。
for i in {0..10}
do
echo "There is/are $i rabbit(s)."
done
for i in {0..15..3}
do
echo "There is/are $i rabbit(s)."
done
for i in {1..9}
do
for j in {1..9}
do
printf " %1d * %1d = %2d" $i $j $(($i * $j))
done
echo ''
done
for i in {1..10}
do
for ((j=$i; j<=10; ++j))
do
echo -n '*'
done
echo ''
done
export TRUTH=(49 20 4C 4F 56 45 20 43 53 49 45)
for letter in ${TRUTH[@]}
do
printf "\x$letter"
done
echo ''
export name=''
while [[ -z $name ]]
do
read -p 'Your name? ' name
done
echo "Hello $name."
export number=2
while :
do
echo "There are $number dogs."
if [[ $number -eq 10 ]]
then
break
fi
export number=$(( $number + 1 ))
done
因為今天的文章內容有點乾,所以只好補張圖化解尷尬氣氛。
圖源傳送門
氣氛現在從尷尬變成非常尷尬。
圖源傳送門
如果對於文章內容有建議、糾錯或圖源標示不正確的問題,歡迎參考 [機派X] Day 1 嘗試與文章作者聯絡。
想看更多本系列的文章,請連結至 [機派X] Day 1 查看大綱。