linux shell 通过 $@ 和 $# 动态处理任意数量参数,用 for arg in "$@" 安全遍历,shift 可移位分离固定与可变参数,必须加双引号防止空格分割,避免使用 $* 或无引号 $@。

Linux Shell 中无法像 C 语言那样直接声明 void func(...) 形式的可变参数函数,但可以通过位置参数 $@、$# 和循环遍历等方式灵活处理任意数量的参数。关键在于不硬编码参数个数,而是动态解析。
用 $@ 和 $# 获取全部参数
$@ 表示所有传入的位置参数(保持各参数独立性),$# 返回参数总个数。这是实现“可变参数”最基础也最可靠的方式。
- 始终用
"$@"(带英文双引号)引用,避免含空格或特殊字符的参数被错误分割 - 用
for arg in "$@"安全遍历每个参数 - 可用
if [ $# -eq 0 ]判断是否无参数,提前退出或给出提示
典型示例:打印所有参数并计数
下面是一个简洁实用的自定义函数:
my_echo() {
if [ $# -eq 0 ]; then
echo "错误:至少需要一个参数"
return 1
fi
echo "共 $# 个参数:"
local i=1
for arg in "$@"; do
echo " [$i] $arg"
((i++))
done
}调用方式:my_echo hello world "foo bar" 42 → 正确识别 4 个参数,第三个含空格也不出错。
进阶技巧:混合固定参数 + 可变参数
若需前几个参数有特定含义(如选项、目标路径),剩余为变长列表,可手动移位:
- 用
shift n将前n个参数“移出”,之后"$@"即为剩余参数 - 例如:函数
deploy host1 host2 --verbose file1.txt file2.log,可先取$1 $2为 hosts,shift 2后再处理其余 - 注意:每次
shift后$#自动更新,适合嵌套解析
避免常见陷阱
很多初学者误用 $* 或不加引号的 $@,导致逻辑断裂:
-
$*会把所有参数拼成单个字符串(用第一个 IFS 字符连接),破坏原始分隔 -
$@不加引号等价于$1 $2 $3...,遇空格即断开 —— 这是最大隐患 - 不要尝试用
${@:2}类似数组切片(Bash 4.3+ 支持,但兼容性差;POSIX sh 完全不支持)











