Bash 開發
Bash 5.1+ 腳本開發的核心模式與最佳實務。提供現代 bash 慣用語法、錯誤處理、引數解析,以及純 bash 替代外部指令的方法。
腳本基礎
每個腳本都從必要的標頭開始:
#!/usr/bin/env bash
set -euo pipefail
set 選項說明:
-e- 指令失敗時立即退出-u- 將未設定變數視為錯誤-o pipefail- 管線中任一指令失敗則整個管線失敗
腳本中繼資料模式
SCRIPT_NAME=$(basename "${BASH_SOURCE[0]}")
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
readonly SCRIPT_VERSION="1.0.0"
readonly SCRIPT_NAME SCRIPT_DIR
錯誤處理
實作基於 trap 的錯誤處理,讓腳本更穩健。
引數解析
標準的引數解析模板。
變數最佳做法
永遠使用大括號並引用變數:
# 正確
"${variable}"
"${array[@]}"
# 錯誤
$variable
${array[*]} # 請使用 [@] 以正確迭代
使用 readonly 宣告常數:
readonly CONFIG_FILE="/etc/app/config"
readonly -a VALID_OPTIONS=("opt1" "opt2" "opt3")
注意: 永遠不要在來源腳本(sourced scripts)中使用 readonly,否則重新載入時會產生錯誤。
字串操作(純 Bash)
優先使用 bash 原生參數擴展,而非外部工具:
# 去除前後空白
trimmed="${string#"${string%%[![:space:]]*}"}"
trimmed="${trimmed%"${trimmed##*[![:space:]]}"}"
# 小寫/大寫(Bash 4+)
lower="${string,,}"
upper="${string^^}"
# 子字串提取
substring="${string:0:10}" # 前 10 個字元
suffix="${string: -5}" # 最後 5 個字元
# 取代模式
replaced="${string//old/new}" # 全部取代
replaced="${string/old/new}" # 取代第一個
# 去除前綴/後綴
no_prefix="${string#prefix}" # 最短匹配
no_prefix="${string##*/}" # 最長匹配(basename)
no_suffix="${string%suffix}" # 最短匹配
no_suffix="${string%%/*}" # 最長匹配
陣列操作
# 宣告
declare -a indexed_array=()
declare -A assoc_array=()
# 安全迭代(搭配 nullglob)
shopt -s nullglob
for file in *.txt; do
process "${file}"
done
shopt -u nullglob
# 陣列長度
length="${#array[@]}"
# 附加元素
array+=("new_element")
# 使用索引迭代
for i in "${!array[@]}"; do
printf '%d: %s\n' "${i}" "${array[i]}"
done
檔案操作
# 讀取檔案至字串
content="$(<"${file}")"
# 讀取檔案至陣列(Bash 4+)
mapfile -t lines < "${file}"
# 檢查檔案狀態
[[ -f "${file}" ]] # 一般檔案存在
[[ -d "${dir}" ]] # 目錄存在
[[ -r "${file}" ]] # 可讀取
[[ -w "${file}" ]] # 可寫入
[[ -x "${file}" ]] # 可執行
[[ -s "${file}" ]] # 非空
# 安全建立暫存檔
temp_file=$(mktemp)
trap 'rm -f "${temp_file}"' EXIT
條件表達式
使用 [[ ]] 進行條件判斷(bash 特有,功能更強大):
# 字串比較
[[ "${var}" == "value" ]] # 相等
[[ "${var}" == pattern* ]] # Glob 匹配
[[ "${var}" =~ ^regex$ ]] # 正規表達式匹配
# 數值比較
(( num > 10 )) # 算術比較
[[ "${num}" -gt 10 ]] # 傳統語法
# 複合條件
[[ -f "${file}" && -r "${file}" ]]
[[ "${opt}" == "a" || "${opt}" == "b" ]]
工具函式
效能指南
- 儘可能使用內建指令,而非外部指令
- 大量資料時使用批次操作,避免迴圈
- 使用
printf而非echo,以獲得更好的可移植性與控制力 - 在緊湊迴圈中避免不必要的子 shell
- 字串比較時使用
[[ ]]而非[ ]
其他資源
參考檔案
如需詳細模式與範例:
- bash_example_file.sh - 完整腳本模板
- bash_example_includes.bash - 可重複使用的工具函式
- bash-agent-notes.md - 情境感知審查指引
- pure-bash-bible-strings.md - 字串操作模式
- pure-bash-bible-arrays.md - 陣列操作
- pure-bash-bible-files.md - 檔案處理模式
- pure-bash-bible-variables.md - 參數擴展參考