Shell脚本编程完全指南
一、基础结构
1. 脚本格式
#!/usr/bin/env bash # Shebang行(推荐可移植写法)
# 单行注释
: <<'COMMENT'
多行注释示例
支持换行文本
COMMENT
2. 执行方式
| 方法 | 命令 | 说明 |
|---|---|---|
| 添加执行权限 | chmod +x script.sh |
使脚本可执行 |
| 直接执行 | ./script.sh |
需执行权限 |
| 解释器执行 | bash script.sh |
无需执行权限 |
| 环境变量执行 | script.sh |
需软链接到$PATH目录 |
调试工具:
bash -n script.sh:语法检查bash -x script.sh:逐行调试(显示执行过程)
二、变量处理
1. 变量类型
| 类型 | 定义方式 | 示例 | 查看命令 |
|---|---|---|---|
| 普通变量 | var="value" |
user="alice" |
echo $user |
| 环境变量 | export var="value" |
export PATH=$PATH:/add |
env |
| 只读常量 | readonly var="value" |
readonly VERSION=1.0 |
readonly |
2. 变量操作
name="Bob"
echo ${name} # 标准引用(推荐)
name+=" Smith" # 追加 → "Bob Smith"
unset name # 删除变量
3. 核心内置变量
| 变量 | 含义 | 变量 | 含义 |
|---|---|---|---|
$PATH |
命令搜索路径 | $? |
上条命令退出状态 |
$UID |
用户ID | $$ |
当前进程PID |
$HOSTNAME |
主机名 | $PPID |
父进程PID |
$HISTSIZE |
历史记录条数 | $RANDOM |
随机数(0-32767) |
三、数据运算
1. 算术运算
let result="10 + 5" # let计算
result=$((10 * 2)) # $(( ))计算
result=$(expr 10 - 3) # expr命令
# 增强赋值
count=5
((count *= 3)) # count=15
((count--)) # count=14
2. 浮点数计算
pi=3.1415926
printf "%.2f\n" $pi # 3.14 (保留两位小数)
result=$(echo "scale=2; 10/3" | bc) # 3.33 (bc计算器)
3. 随机数生成
echo $((RANDOM % 100)) # 0-99随机数
echo $((RANDOM % 50 + 1)) # 1-50随机数
四、条件测试
1. 测试语法
test -f file.txt # 传统写法
[ -d "/data" ] # 常用写法(注意空格)
[[ $str =~ ^[A-Z] ]] # 正则匹配(高级模式)
2. 测试选项速查
| 类型 | 选项 | 含义 | 示例 |
|---|---|---|---|
| 文件测试 | -e |
文件是否存在 | [ -e "file" ] |
-f |
是否为普通文件 | [ -f "/path" ] |
|
-x |
是否可执行 | [ -x "/bin/ls" ] |
|
| 字符串 | -z |
字符串为空 | [ -z "$var" ] |
== |
字符串相等 | [[ "$s1" == "$s2" ]] |
|
| 数值比较 | -eq |
等于 | [ $n1 -eq 10 ] |
-gt |
大于 | [ $n1 -gt $n2 ] |
|
| 逻辑组合 | && |
与 (AND) | [ cond1 ] && [ cond2 ] |
| ` | ` |
五、流程控制
1. 条件分支
if语句
if [[ $age -ge 18 ]]; then
echo "成年人"
elif [[ $age -ge 13 ]]; then
echo "青少年"
else
echo "儿童"
fi
case语句
case $OS in
Linux)
echo "使用 apt/yum"
;;
Darwin)
echo "使用 brew"
;;
*)
echo "未知系统: $OS"
exit 1
;;
esac
2. 循环结构
for循环
# 列表遍历
for file in *.log; do
gzip "$file"
done
# C语言风格
for ((i=0; i<10; i+=2)); do
echo "偶数: $i"
done
# 数字序列
for i in $(seq 5); do
echo "计数: $i"
done
while/until循环
# while:条件为真执行
count=1
while [[ $count -le 5 ]]; do
echo "While: $count"
((count++))
done
# until:条件为假执行
until [[ $count -gt 10 ]]; do
echo "Until: $count"
((count++))
done
六、函数与输入输出
1. 函数定义
# 定义函数
disk_usage() {
local threshold=80 # 局部变量
usage=$(df -h / | awk 'NR==2 {print $5}' | tr -d '%')
if ((usage > threshold)); then
echo "警告: 磁盘使用率 ${usage}% > ${threshold}%"
return 1
fi
return 0
}
# 调用函数
disk_usage
2. 用户输入
read -t 15 -p "用户名: " username # -t:超时(秒)
read -s -p "密码: " passwd # -s:隐藏输入
# 多变量读取
read first last <<< "John Doe"
3. 输入输出重定向
cmd > file # 标准输出重定向(覆盖)
cmd >> file # 标准输出重定向(追加)
cmd 2> file # 错误输出重定向
cmd &> file # 所有输出重定向
# 管道高级用法
echo "data" | {
read input
process "$input"
echo "结果: $result"
}
七、Shell配置文件
1. 配置文件分类
| 文件 | 作用范围 | 加载时机 | 主要用途 |
|---|---|---|---|
/etc/profile |
全局 | 登录Shell | 系统环境变量、启动程序 |
/etc/bashrc |
全局 | 交互式非登录Shell | 全局别名、函数定义 |
~/.bash_profile |
用户 | 登录Shell | 用户环境变量、个人初始化 |
~/.bashrc |
用户 | 交互式Shell | 用户别名、函数、提示符设置 |
2. 加载顺序
登录Shell:
/etc/profile → ~/.bash_profile → ~/.bashrc → /etc/bashrc
非登录交互式Shell:
~/.bashrc → /etc/bashrc
八、高级技巧
1. 变量操作
位置变量
#!/bin/bash
echo "脚本名: $0"
echo "第一个参数: $1"
echo "所有参数: $@"
echo "参数个数: $#"
异或交换
a=10; b=20
a=$((a^b)); b=$((a^b)); a=$((a^b))
echo "a=$a, b=$b" # a=20, b=10
2. 安全脚本
#!/usr/bin/env bash
set -e # 命令失败立即退出
set -u # 使用未定义变量时报错
set -o pipefail # 管道中任意命令失败则整体失败
# 安全删除示例
readonly BACKUP_DIR="/backups"
[[ -d "$BACKUP_DIR" ]] || exit 1
rm -rf "$BACKUP_DIR"/*
3. 子进程控制
# () 创建子进程(变量隔离)
(var=100; echo "子进程: $var") # 输出100
echo "父进程: $var" # 空值
# {} 当前进程执行(共享变量)
{ var=200; echo "当前进程: $var"; } # 200
echo "当前进程: $var" # 200
4. 实用代码片段
进度条显示
for i in {1..20}; do
printf "\r[%-20s] %d%%" $(printf "%${i}s" | tr ' ' '#') $((i*5))
sleep 0.1
done
echo
浮点数比较
compare_floats() {
result=$(echo "$1 > $2" | bc)
[[ $result -eq 1 ]] && echo "$1 > $2" || echo "$1 <= $2"
}
compare_floats 3.14 2.71 # 3.14 > 2.71
九、最佳实践
- 变量引用:始终用
${var}替代$var - 错误处理:关键操作检查退出码
if ! cmd; then... - 路径处理:使用绝对路径,避免依赖当前目录
- 兼容性:重要脚本声明Shell版本
#!/usr/bin/env bash - 调试:复杂脚本使用
set -x调试模式
通过
bash -n script.sh进行静态检查,shellcheck工具可提供更专业的检查