Shell脚本参数索引替换报错:间接引用与算术表达式替换问题
Shell间接参数引用的语法问题解答
一、${!i}的原理说明
这是Bash的间接参数扩展语法,和表示逻辑非的!没有任何关系。它的作用是:
- 先读取变量
i的数值(比如你例子里的1) - 把这个数值当作位置参数的索引(比如
1对应$1,2对应$2) - 最终取出对应位置参数的内容
所以你执行./testo A B时,${!i}等价于$1输出A,${!k}等价于$2输出B。
二、你的写法报错的原因
${!parameter}的语法规则要求:感叹号后面必须是合法的变量名/参数名,或者是能直接展开为参数名的变量引用。而你尝试的${!$((i+1))}、${!((i+1))}这类写法,是把算术表达式直接嵌套进了间接扩展语法里,Bash无法解析这种嵌套的替换逻辑,因此抛出bad substitution错误。
三、正确的替换方式
方法1:使用eval实现动态引用
eval可以帮你先解析算术表达式,再扩展参数引用:
eval echo "\${$((i+1))}"
执行逻辑:
$((i+1))先计算出结果2eval会把${2}解析为脚本的第二个位置参数,最终输出B
方法2:保留临时变量(推荐)
虽然多一行代码,但可读性和可维护性更好,也是最不容易出错的方式:
k=$((i+1)) echo "${!k}"
方法3:Bash 4.3+专属的nameref特性
如果你的Bash版本在4.3及以上,可以用命名引用简化:
declare -n idx=$((i+1)) echo "$idx"
declare -n会把idx变成一个指向对应位置参数的引用变量,直接输出idx就能得到目标参数的值。
内容的提问来源于stack exchange,提问作者udippel
相关产品推荐
相关产品推荐

