條件判斷
腳本跟互動指令的差別,多半就在「如果失敗就停、如果檔存在才複製」。Bash 用結束碼判斷真假:0 為真(成功),非 0 為假。
if 的形狀
if grep -q error app.log; then
echo "發現錯誤"
elif grep -q warn app.log; then
echo "只有警告"
else
echo "看起來正常"
fi
then / fi 是固定關鍵字。條件位置其實就是一道指令;grep -q 找到就回傳 0。
一行寫:
&&:左邊成功才做右邊。||:左邊失敗才做右邊。
test 與 [[ ]]
檔案與字串比對用 test,常見寫成 [ ](兩邊要空格):
| 條件 | 意義 |
|---|---|
-f |
一般檔存在 |
-d |
目錄存在 |
-e |
存在(任何類型) |
-x |
可執行 |
-z "$s" |
字串長度為 0 |
-n "$s" |
字串非空 |
"$a" = "$b" |
字串相等(不要寫成 == 在單括號裡硬記兩套) |
"$n" -gt 10 |
整數大於(另有 -eq -lt -ge -le -ne) |
Bash 還有 [[ ]],比較不容易被空白與萬用字元咬到,也支援 &&、||、=~ 正規表示式:
if [[ $name == alice && -d $HOME ]]; then
echo "ok"
fi
if [[ $email =~ ^[^@]+@[^@]+$ ]]; then
echo "像是 email"
fi
新腳本建議用 [[ ]];看舊教材時要認得 [ ] 是同一類東西。
case
多個固定字串用 case 比一串 elif 清楚:
case "$1" in
start) echo "啟動" ;;
stop) echo "停止" ;;
restart) echo "重啟" ;;
*) echo "用法:$0 {start|stop|restart}" >&2
exit 1 ;;
esac
;; 結束一個分支,*) 是預設。錯誤訊息丟到 >&2(stderr),結束碼用非 0。
結束碼
有 set -e 時,失敗的 cp 會直接讓腳本結束,不一定要手動查 $?。需要「失敗也繼續」時再檢查 $? 或用 if cp ...; then。
crontab 與 CI 都靠結束碼決定要不要告警。
總結
條件就是指令成不成功。檔案與字串用 [[ ]],多個固定選項用 case,對外失敗用 exit 1。重複做同一件事則看 迴圈。