Bash 脚本速查表
Bash 是 Linux 和 macOS 上最常用的 Shell 脚本语言。本速查表按语法类别整理了 Bash 脚本开发的常用语法和命令,从变量定义到作业控制,每个语法点都有实际使用示例。无论你是刚学 Shell 编程还是需要快速查阅某个语法,这份速查表都能帮到你。
使用场景速查
| 你要做什么 | 用哪个语法 |
| 定义变量 | name='value' |
| 条件判断 | if [[ condition ]]; then |
| 数字循环 | for i in {1..10}; do |
| 文件循环 | while read line; do |
| 定义函数 | function_name() { ... } |
| 创建数组 | arr=(a b c) |
| 读取输入 | read -p "提示" var |
| 命令替换 | result=$(command) |
| 后台运行 | command & |
变量操作
``bash
# 变量赋值与引用
name='world' # 字符串赋值(等号两侧无空格)
age=42 # 数字赋值(无需引号)
echo "Hello, $name" # 美元符号引用变量
echo "Age is ${age}" # 花括号形式(用于拼接)
echo "${name}_suffix" # 拼接:world_suffix
# 只读变量 readonly PI=3.14159 # 声明为只读(不可修改) declare -r GRAVITY=9.8 # 另一种只读方式
# 删除变量 unset name # 删除变量(设为空)
# 特殊变量
echo "$0" # 脚本名称
echo "$1 $2 $3" # 位置参数(第1/2/3个参数)
echo "$#" # 参数个数
echo "$@" # 所有参数列表
echo "$?" # 上条命令退出码(0=成功)
echo "$$" # 当前进程 PID
echo "$RANDOM" # 随机数(0-32767)
`
条件判断
`bash
# if / then / else / fi
if [[ $age -ge 18 ]]; then
echo "成年人"
elif [[ $age -ge 60 ]]; then
echo "老年人"
else
echo "未成年人"
fi
# test 命令(兼容 POSIX) if [ "$name" = "world" ]; then echo "匹配" fi
# 字符串比较 [[ "$name" == "world" ]] # 相等(模式匹配) [[ "$name" != "hello" ]] # 不等 [[ -z "$var" ]] # 字符串为空 [[ -n "$var" ]] # 字符串非空
# 数字比较 [[ $age -eq 42 ]] # 等于(equal) [[ $age -ne 0 ]] # 不等于(not equal) [[ $age -gt 18 ]] # 大于(greater than) [[ $age -ge 18 ]] # 大于等于 [[ $age -lt 60 ]] # 小于(less than) [[ $age -le 60 ]] # 小于等于
# 文件测试 [[ -f "file.txt" ]] # 是否为普通文件 [[ -d "dir/" ]] # 是否为目录 [[ -e "path" ]] # 路径是否存在 [[ -s "file" ]] # 文件非空 [[ -r "file" ]] # 文件可读 [[ -w "file" ]] # 文件可写 [[ -x "file" ]] # 文件可执行
# 逻辑运算 [[ -n "$var" && $age -gt 0 ]] # 逻辑与(AND) [[ -z "$var" || $age -eq 0 ]] # 逻辑或(OR) [[ ! -f "file" ]] # 逻辑非(NOT)
# case 语句
case "$os" in
linux|Linux)
echo "Linux 系统"
;;
darwin|macos)
echo "macOS 系统"
;;
*)
echo "未知系统"
;;
esac
`
循环控制
`bash
# for 循环(数字范围)
for i in {1..5}; do
echo "数字: $i"
done
# for 循环(列表) for fruit in apple banana orange; do echo "水果: $fruit" done
# for 循环(C 风格) for (( i=0; i
# for 循环(通配符展开) for file in *.sh; do echo "脚本: $file" done
# while 循环 count=1 while [[ $count -le 5 ]]; do echo "计数: $count" ((count++)) done
# while 逐行读取文件 while IFS= read -r line; do echo "行: $line" done < input.txt
# until 循环 until [[ $count -gt 5 ]]; do echo "count = $count" ((count++)) done
# break 和 continue
for i in {1..10}; do
[[ $i -eq 3 ]] && continue # 跳过 3
[[ $i -eq 8 ]] && break # 到 8 停止
echo "i = $i"
done
# 输出: 1 2 4 5 6 7
`
函数定义
`bash
# 简单函数定义
greet() {
echo "Hello, $1!"
}
# 调用函数 greet "Alice" # 输出: Hello, Alice!
# 带 return 的函数 add() { local a=$1 b=$2 return $((a + b)) } add 3 4 echo "$?" # 输出: 7(return 限制 0-255)
# 带返回结果的函数(推荐用 echo) multiply() { local a=$1 b=$2 echo $((a * b)) # 用 echo 输出结果 } result=$(multiply 6 7) echo "$result" # 输出: 42
# local 变量 myfunc() { local local_var="仅函数内可见" global_var="全局可见" echo "$local_var" }
# 默认参数值 say_hello() { local name=${1:-"World"} # 默认值 World echo "Hello, $name" }
# 获取所有参数
print_args() {
for arg in "$@"; do
echo "参数: $arg"
done
}
`
数组操作
`bash
# 定义数组
fruits=("apple" "banana" "orange")
numbers=(1 2 3 4 5)
# 索引访问 echo "${fruits[0]}" # 输出: apple echo "${fruits[-1]}" # 输出: orange(最后元素)
# 所有元素 echo "${fruits[@]}" # 所有元素(以空格分隔) echo "${fruits[*]}" # 所有元素(IFS 拼接)
# 数组长度 echo "${#fruits[@]}" # 输出: 3
# 添加元素 fruits+=("grape") # 追加 fruits[10]="kiwi" # 指定索引添加(数组会扩展)
# 删除元素 unset fruits[1] # 删除索引 1(banana) unset fruits # 删除整个数组
# 切片 arr=(a b c d e) echo "${arr[@]:1:3}" # 输出: b c d(索引1开始取3个) echo "${arr[@]:2}" # 从索引2到结尾
# 关联数组(Bash 4+)
declare -A user
user[name]="Alice"
user[age]=30
user[city]="Beijing"
echo "${user[name]}" # 输出: Alice
echo "${!user[@]}" # 输出所有键: name age city
`
输入输出
`bash
# echo 输出
echo "Hello World" # 默认换行
echo -n "不换行" # -n 不换行
echo -e "Tab:\there" # -e 启用转义(\\t \\n 等)
# printf 格式化输出 printf "名称: %s, 数量: %d\\n" "苹果" 5
# read 输入 read -p "请输入名字: " name # 带提示的输入 read -s -p "密码: " pass # -s 不回显(适合密码) read -t 5 -p "5秒内输入: " var # -t 超时
# 重定向 command > file # stdout 写入文件(覆盖) command >> file # stdout 追加到文件 command 2> error.log # stderr 重定向 command &> output.log # stdout + stderr 一起重定向 command < input.txt # 文件作为 stdin
# 管道 cmd1 | cmd2 # cmd1 的输出作为 cmd2 的输入
# Here Document cat << EOF 这是多行文本 可以包含变量 $HOME EOF
# Here String grep "abc" <<< "abcdef" # 字符串作为 stdin
# tee(同时输出到文件和屏幕)
echo "日志" | tee log.txt
`
命令替换与扩展
`bash
# 命令替换:两种等价语法
today=$(date +%Y-%m-%d) # 推荐:现代语法 $()
today2=date +%Y-%m-%d # 旧式:反引号
# 算术扩展 echo $((5 + 3 * 2)) # 输出: 11 echo $(( (a + b) % 10 )) # 使用变量 num=$((RANDOM % 100 + 1)) # 随机 1-100
# let 命令 let "x = 10" let "x += 5"
# 参数扩展 - 默认值 echo "${var:-默认值}" # 如果 var 未设置或为空,使用默认值(不修改 var) echo "${var:=默认值}" # 如果 var 未设置或为空,赋默认值并返回 echo "${var:?错误信息}" # 如果 var 未设置或为空,打印错误并退出 echo "${var:+替换值}" # 如果 var 已设置且非空,使用替换值
# 参数扩展 - 字符串操作 echo "${#str}" # 字符串长度 echo "${str:0:3}" # 子串(从索引0取3个) echo "${str#prefix}" # 去除最短前缀 echo "${str##prefix}" # 去除最长前缀 echo "${str%suffix}" # 去除最短后缀 echo "${str%%suffix}" # 去除最长后缀 echo "${str/a/b}" # 替换第一个匹配 echo "${str//a/b}" # 替换所有匹配 echo "${str^^}" # 转大写 echo "${str,,}" # 转小写
# 花括号扩展 echo {a,b,c}.txt # 输出: a.txt b.txt c.txt echo {1..5} # 输出: 1 2 3 4 5 echo {01..10} # 输出: 01 02 ... 10 echo file{1..3}.txt # 输出: file1.txt file2.txt file3.txt
# 进程替换
diff <(ls dir1) <(ls dir2) # 比较两个目录的输出
`
作业控制
`bash
# 后台运行
sleep 100 & # 后台运行,返回 job ID 和 PID
# 查看后台作业 jobs # 列出所有后台作业 jobs -l # 列出后台作业及 PID
# 前台/后台切换 fg %1 # 将 job 1 调回前台 bg %1 # 将暂停的 job 1 放入后台继续运行
# 暂停与终止 Ctrl+z # 暂停当前前台进程 Ctrl+c # 终止当前前台进程 kill %1 # 终止 job 1 kill -9 1234 # 强制终止 PID 1234
# nohup(关闭终端后继续运行) nohup long-task.sh & # 终端关闭后仍运行
# disown(从当前 Shell 分离) command & disown # 解除关联,关闭终端不会终止
# trap(信号处理) cleanup() { echo "清理临时文件..." rm -rf /tmp/temp_* } trap cleanup EXIT # 脚本退出时执行 cleanup trap 'echo "按了 Ctrl+C"' INT # 捕获 Ctrl+C trap 'echo "收到信号"' TERM # 捕获终止信号 ``
变量操作(4)
| 命令 | 难度 | ||
|---|---|---|---|
name=value变量赋值(等号两侧不能有空格) | 基础 | name='world' | |
readonly / declare -r声明只读变量(不可修改) | 中级 | readonly PI=3.14159 | |
unset删除变量或数组元素 | 基础 | unset name | |
$0 $1 $# $@ $?特殊变量 — 脚本名、参数、个数、退出码 | 中级 | echo "$0 $# $?" |
条件判断(6)
| 命令 | 难度 | ||
|---|---|---|---|
if [[ condition ]]; then ... fi条件判断语句(双中括号,支持模式匹配) | 基础 | if [[ $age -ge 18 ]]; then echo "Adult"; fi
| |
[ condition ]POSIX 兼容的条件测试 | 基础 | [ "$name" = "world" ] | |
-eq / -ne / -gt / -lt / -ge / -le数字比较运算符 | 基础 | [[ $age -gt 18 ]] | |
-f / -d / -e / -r / -w / -x文件测试运算符 | 中级 | [[ -f "file.txt" ]] | |
&& / || / !逻辑与、或、非 | 中级 | [[ -n "$var" && $age -gt 0 ]] | |
case ... esac多分支条件匹配 | 中级 | case "$os" in linux|Linux) echo "Linux";; *) echo "Other";; esac
|
循环控制(5)
| 命令 | 难度 | ||
|---|---|---|---|
for i in {1..5}; do ... donefor 循环(数字范围) | 基础 | for i in {1..5}; do echo $i; done | |
for (( i=0; i<5; i++ )); do ... doneC 风格 for 循环 | 中级 | for (( i=0; i<5; i++ )); do echo $i; done | |
while [[ condition ]]; do ... donewhile 条件循环 | 基础 | while [[ $count -le 5 ]]; do echo $count; ((count++)); done | |
until [[ condition ]]; do ... doneuntil 条件循环(条件为假时执行) | 中级 | until [[ $count -gt 5 ]]; do echo $count; ((count++)); done | |
break / continue跳出循环 / 跳过本次迭代 | 中级 | for i in {1..10}; do [[ $i -eq 3 ]] && continue; done |
函数定义(4)
| 命令 | 难度 | ||
|---|---|---|---|
function_name() { ... }定义函数 | 基础 | greet() { echo "Hello, $1!"; } | |
local var=value声明局部变量(仅在函数内可见) | 中级 | local name=$1 | |
return从函数返回(0-255 的整数退出码) | 中级 | return $((a + b)) | |
${1:-default}函数参数的默认值 | 中级 | local name=${1:-"World"} |
数组操作(4)
| 命令 | 难度 | ||
|---|---|---|---|
arr=(a b c)定义索引数组 | 基础 | fruits=("apple" "banana" "orange") | |
${arr[@]} / ${#arr[@]}数组所有元素 / 数组长度 | 基础 | echo "${fruits[@]}" | |
arr+=("item")向数组追加元素 | 中级 | fruits+=("grape") | |
declare -A map定义关联数组(Bash 4+) | 高级 | declare -A user; user[name]="Alice" |
输入输出(6)
| 命令 | 难度 | ||
|---|---|---|---|
echo输出文本到标准输出 | 基础 | echo -e "Tab:\there" | |
printf格式化输出(类似 C 语言的 printf) | 中级 | printf "Name: %s, Count: %d\\n" "Apple" 5 | |
read从标准输入读取 | 基础 | read -p "Enter name: " name | |
> / >> / 2> / &> / <输入输出重定向 | 基础 | command &> output.log | |
|管道 — 将前一个命令的输出作为后一个命令的输入 | 基础 | cmd1 | cmd2 | |
cat << EOFHere Document — 多行输入 | 中级 | cat << EOF\\n多行文本\\nEOF |
替换与扩展(6)
| 命令 | 难度 | ||
|---|---|---|---|
$(command)命令替换 — 将命令输出赋值给变量 | 基础 | today=$(date +%Y-%m-%d) | |
$(( arithmetic ))算术扩展 — 执行整数运算 | 基础 | echo $((5 + 3 * 2)) | |
${var:-default} / ${var:=default} / ${var:?err}参数扩展 — 默认值、赋值默认、错误退出 | 中级 | echo "${var:-default}" | |
${#str} / ${str:0:3} / ${str//a/b} / ${str^^}参数扩展 — 长度、子串、替换、大小写转换 | 中级 | echo "${str//old/new}" | |
{a,b,c} / {1..10}花括号扩展 — 生成字符串序列 | 中级 | echo {a,b,c}.txt | |
<(command)进程替换 — 将命令输出作为文件传递 | 高级 | diff <(ls dir1) <(ls dir2) |
作业控制(6)
| 命令 | 难度 | ||
|---|---|---|---|
command &后台运行命令 | 基础 | sleep 100 & | |
jobs列出当前 Shell 的后台作业 | 基础 | jobs -l | |
fg / bg将作业调至前台 / 后台继续运行 | 中级 | fg %1 | |
kill终止进程或作业 | 中级 | kill -9 1234 | |
nohup使进程忽略 SIGHUP(关闭终端后继续运行) | 中级 | nohup long-task.sh & | |
trap捕获信号并执行自定义处理 | 高级 | trap cleanup EXIT |