位置参数变量
Shell 位置参数变量:处理命令行传参的实用指南
在 Shell 脚本中,位置参数变量用于接收和处理命令行传入的参数,是实现脚本灵活性和复用性的关键。无论是简单的参数传递还是复杂的批量处理,掌握位置参数变量都能高效完成任务。以下是详细解析和示例。
基础位置参数变量
1. $n:按序号获取参数
$0:表示脚本本身的名称(包含路径时显示完整路径)。$1~$9:表示第 1 到第 9 个参数。${10}及以上:10 个以上的参数需用大括号包裹(如${10}、${11})。
示例:params.sh 脚本
echo "脚本名称:$0"
echo "第1个参数:$1"
echo "第2个参数:$2"
echo "第10个参数:${10}"
执行脚本:
sh params.sh a b c d e f g h i j k
输出:
脚本名称:params.sh
第1个参数:a
第2个参数:b
第10个参数:j
2. $#:获取参数总数
- 表示命令行传入的参数总个数(不包含脚本名称
$0)。
示例:统计参数个数
echo "参数总数:$# 个"
# 判断参数是否足够
if [ $# -lt 2 ]; then
echo "错误:至少需要传入2个参数!"
exit 1 # 非0退出表示执行失败
fi
执行脚本:
sh count_params.sh 1 2 3
# 输出:参数总数:3 个
批量处理所有参数
1. $* 与 $@:获取所有参数
两者都表示命令行中的所有参数,但处理方式不同:
$*:将所有参数视为一个整体字符串(用空格分隔)。$@:将每个参数视为独立的字符串(保留参数边界)。
示例:对比 $* 和 $@
echo "使用 \$* 遍历:"
for param in "$*"; do
echo "- $param"
done
echo -e "\n使用 \$@ 遍历:"
for param in "$@"; do
echo "- $param"
done
执行脚本:
sh all_params.sh a "b c" d
输出:
使用 $* 遍历:
- a b c d # 所有参数被合并为一个字符串
使用 $@ 遍历:
- a # 保持原参数结构("b c"作为一个参数)
- b c
- d
结论:遍历参数时优先使用 $@,能正确保留包含空格的参数。
2. 截取部分参数
通过 ${@:起点} 或 ${@:起点:个数} 可截取部分参数:
${@:n}:从第n个参数开始,获取后面所有参数(n从 1 开始)。${@:n:m}:从第n个参数开始,获取m个参数。
示例:截取参数
echo "所有参数:$@"
echo "从第2个参数开始:${@:2}"
echo "从第2个参数开始,取2个:${@:2:2}"
执行脚本:
sh slice_params.sh 10 20 30 40 50
输出:
所有参数:10 20 30 40 50
从第2个参数开始:20 30 40 50
从第2个参数开始,取2个:20 30
特殊变量 $?:获取执行状态
$? 用于获取上一条命令的退出状态码:
0:命令执行成功。- 非 0:命令执行失败(不同数值表示不同错误类型)。
示例:检查命令执行结果
# 尝试创建目录
mkdir test_dir
if [ $? -eq 0 ]; then
echo "目录创建成功!"
else
echo "目录创建失败!"
fi
执行脚本:
sh check_status.sh
# 首次执行输出:目录创建成功!
# 再次执行(目录已存在)输出:目录创建失败!
实际应用案例
1. 简单计算器脚本
接收两个数字和一个运算符,计算结果:
# 文件名:calculator.sh
if [ $# -ne 3 ]; then
echo "用法:$0 数字1 运算符 数字2"
echo "示例:$0 10 + 20"
exit 1
fi
num1=$1
op=$2
num2=$3
case $op in
+) result=$((num1 + num2)) ;;
-) result=$((num1 - num2)) ;;
*) echo "不支持的运算符:$op"; exit 1 ;;
esac
echo "$num1 $op $num2 = $result"
执行脚本:
sh calculator.sh 15 + 35
# 输出:15 + 35 = 50
2. 批量文件重命名
将指定目录下的所有.txt文件添加前缀(第一个参数为前缀,第二个参数为目录):
# 文件名:rename_files.sh
prefix=$1
dir=${2:-.} # 默认为当前目录
# 校验参数
if [ -z "$prefix" ]; then
echo "用法:$0 前缀 [目录]"
exit 1
fi
# 遍历目录下的txt文件
for file in "$dir"/*.txt; do
# 跳过不存在的文件(避免通配符未匹配的情况)
[ -f "$file" ] || continue
# 获取文件名(不含路径)
filename=$(basename "$file")
# 重命名
mv "$file" "$dir/$prefix$filename"
echo "已重命名:$filename → $prefix$filename"
done
执行脚本:
sh rename_files.sh "2025_" ./docs
# 输出:已重命名:readme.txt → 2025_readme.txt
注意事项
- 参数边界处理:
脚本中应检查参数个数是否符合要求(如用if [ $# -lt N ]),避免因参数缺失导致错误。 - 特殊字符处理:
若参数包含空格、星号(*)等特殊字符,传入时需用双引号包裹(如sh script.sh "hello world")。 - 位置参数的偏移:
可通过shift命令左移参数(如shift 2表示丢弃前 2 个参数,$3变为新的$1),适合处理不定长参数