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")
注意: 在源引(source)的脚本中切勿使用 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* ]] # 通配符匹配
[[ "${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 - 参数扩展参考