Shell 脚本参数详解:从基础到高级应用
-
-
- [Shell 脚本参数详解:从基础到高级应用](#Shell 脚本参数详解:从基础到高级应用)
-
- **一、基础位置参数**
- **二、特殊状态参数**
- **三、参数扩展与操作**
- **四、选项处理进阶**
-
- [1. `getopts` 内置命令(轻量级)](#1.
getopts内置命令(轻量级)) - [2. `getopt` 外部命令(复杂选项)](#2.
getopt外部命令(复杂选项))
- [1. `getopts` 内置命令(轻量级)](#1.
- **五、参数传递实践技巧**
-
- [1. 安全处理含空格参数](#1. 安全处理含空格参数)
- [2. 动态参数解析](#2. 动态参数解析)
- [3. 参数默认值设置](#3. 参数默认值设置)
- **六、调试与验证参数**
- 总结
-
Shell 脚本参数详解:从基础到高级应用
Shell 脚本通过参数接收用户输入,实现动态行为。以下是各类参数的详细说明、使用场景及示例:
一、基础位置参数
脚本执行时传入的参数按顺序分配:
bash
./script.sh arg1 arg2 arg3
| 符号 | 含义 | 示例 | 说明 |
|---|---|---|---|
$0 |
脚本自身名称 | echo $0 → ./script.sh |
包含路径(可用 basename $0 提取纯文件名) |
$1 |
第一个参数 | echo $1 → arg1 |
若参数含空格需用引号包裹:"./script.sh 'hello world'" |
$2 |
第二个参数 | echo $2 → arg2 |
|
$n |
第 n 个参数 | $3 → arg3 |
超过 9 时需用花括号:${10} |
$# |
参数总数 | echo $# → 3 |
常用于循环控制 |
$* |
所有参数(单字符串) | echo $* → arg1 arg2 arg3 |
用 IFS 分隔(默认空格) |
$@ |
所有参数(独立字符串) | for i in "$@"; do ... |
推荐使用,保留参数边界(即使含空格) |
📌 关键区别:
bashargs=("a b" c) # 两个参数:第一个是"a b",第二个是"c" for x in "$*"; do echo "[$x]"; done # 输出:[a b c](合并为单字符串) for x in "$@"; do echo "[$x]"; done # 输出:[a b] 和 [c](独立字符串)
二、特殊状态参数
| 符号 | 含义 | 示例场景 |
|---|---|---|
$? |
上一条命令的退出状态码 | `grep "text" file |
$$ |
当前脚本的进程 ID (PID) | echo "PID: $$" → PID: 12345(用于日志/锁文件) |
$! |
最后一个后台进程的 PID | sleep 100 & echo "Background PID: $!" → Background PID: 12346 |
$_ |
上一条命令的最后一个参数 | ls /tmp; cd $_ → 进入 /tmp 目录 |
$- |
当前 Shell 的选项标志 | echo $- → hB(显示 set 启用的选项如 -e, -x) |
三、参数扩展与操作
通过 ${} 对参数进行高级处理:
| 语法 | 作用 | 示例 |
|---|---|---|
${var:-default} |
若 var 未设置/为空,则用 default | echo ${NAME:-Guest} → 输出 Guest |
${var:=default} |
若 var 未设置/为空,则赋值为 default | : ${PORT:=8080} → 设置 PORT=8080 |
${var:?error_msg} |
若 var 未设置/为空,报错退出 | ${DB_PASS:?密码未设置!} |
${var:+alternate} |
若 var 已设置,则用 alternate | ${DEBUG:+调试模式} → DEBUG 非空时生效 |
${#var} |
变量长度 | NAME="Alice"; echo ${#NAME} → 5 |
${var:offset} |
子串截取(从 offset 开始) | TEXT="Hello"; echo ${TEXT:1} → ello |
${var:offset:length} |
截取子串(指定长度) | ${TEXT:1:3} → ell |
${var#pattern} |
删除最短前缀匹配 | FILE="/path/to/file.txt"; echo ${FILE#*/} → path/to/file.txt |
${var##pattern} |
删除最长前缀匹配 | ${FILE##*/} → file.txt |
${var%pattern} |
删除最短后缀匹配 | ${FILE%.*} → /path/to/file |
${var%%pattern} |
删除最长后缀匹配 | ${FILE%%.*} → /path/to/file |
${var/old/new} |
单次替换 | echo ${FILE/txt/pdf} → /path/to/file.pdf |
${var//old/new} |
全局替换 | echo ${PATH//\:/ } → 用空格分隔 PATH |
${var^} / ${var^^} |
首字母/全部大写 | echo ${name^} → "Alice" |
${var,} / ${var,,} |
首字母/全部小写 | echo ${NAME,,} → "alice" |
四、选项处理进阶
1. getopts 内置命令(轻量级)
处理短选项(-a, -b value):
bash
#!/bin/bash
while getopts "a:b:" opt; do # 定义选项:a 无参,b 需参
case $opt in
a) echo "-a 参数: $OPTARG" ;; # 错误:$OPTARG 仅在需参选项有效
b) echo "-b 参数: $OPTARG" ;; # 正确:$OPTARG 捕获值
?) echo "无效选项: -$OPTARG"; exit 1 ;;
esac
done
shift $((OPTIND-1)) # 移除已处理选项,剩余作为参数
echo "剩余参数: $@"
运行:./script.sh -a test -b hello world
输出:
-a 参数: ? # 错误:$OPTARG 未定义(因 -a 未声明需参)
-b 参数: hello
剩余参数: world # "test" 被忽略(因未在选项中定义)
2. getopt 外部命令(复杂选项)
支持长选项(--help):
bash
#!/bin/bash
TEMP=$(getopt -o a::b: --long arg:,bravo: -n 'script.sh' -- "$@")
eval set -- "$TEMP" # 重设位置参数
while true; do
case "$1" in
-a|--arg) ARG_A="$2"; shift 2 ;; # 可选参数(::)
-b|--bravo) ARG_B="$2"; shift 2 ;;
--) shift; break ;;
*) echo "内部错误!"; exit 1 ;;
esac
done
echo "ARG_A=$ARG_A, ARG_B=$ARG_B, 剩余参数=$@"
五、参数传递实践技巧
1. 安全处理含空格参数
bash
# 错误写法(参数被拆分)
cp $1 $2 # 若 $1="my file.txt" 会拆成两个参数
# 正确写法
cp "$1" "$2" # 保留原始边界
2. 动态参数解析
bash
# 遍历所有参数
for arg in "$@"; do
if [[ $arg == --* ]]; then
option="${arg#--}" # 移除 "--" 前缀
else
values+=("$arg") # 收集参数值
fi
done
3. 参数默认值设置
bash
# 方法1:位置参数扩展
output_file="${1:-result.log}" # 若 $1 为空则用 result.log
# 方法2:条件判断
if [ -z "$1" ]; then
input_file="default.in"
else
input_file="$1"
fi
六、调试与验证参数
bash
# 打印所有参数详情
echo "脚本名: $0"
echo "参数数: $#"
echo "所有参数: $@"
echo "参数列表:"
for i in $(seq 1 $#); do
eval echo "\$$i = \${$i}"
done
# 检查必需参数
if [ $# -lt 2 ]; then
echo "用法: $0 <input> <output>" >&2
exit 1
fi
总结
| 类别 | 核心参数 | 应用场景 |
|---|---|---|
| 基础位置参数 | $0, $1..$9, $@, $# |
接收用户输入,循环处理 |
| 状态参数 | $?, $$, $! |
错误处理、进程管理 |
| 参数扩展 | ${var:-def}, ${#var}, ${var//old/new} |
安全赋值、字符串操作、默认值设置 |
| 选项解析 | getopts, getopt |
处理 -v/--verbose 类命令行开关 |
掌握这些参数机制,可编写出健壮、灵活的 Shell 脚本,适应从简单自动化到复杂运维任务的各种场景。