Shell两层数组嵌套遍历出现bad substitution错误该如何解决
问题原因
Bash 原生不支持连续嵌套的参数扩展语法,${${i}[*]} 这种写法不符合 Bash 语法规则,因此会抛出 bad substitution 错误。
可行解决方案
以下提供两种适配不同场景的实现方式:
方案1:使用 nameref 间接引用(推荐,Bash 4.3+ 支持)
Bash 4.3 及以上版本支持 declare -n 声明名称引用,可以直接将变量绑定到对应的数组,语法清晰安全性高:
a=(1 2) b=(3 4 5 6) c=(7 8 9) z=(a b c) # 遍历外层数组优先用 "${z[@]}" 而非 ${z[*]},避免带空格的元素被错误拆分 for i in "${z[@]}" do # 声明 arr 为名称引用,指向 i 对应的数组 declare -n arr="$i" for j in "${arr[@]}" do # 按需调整输出内容,原代码输出 $i 此处示例输出数组名和对应元素 echo "数组 $i 的元素:$j" done # 取消名称引用绑定,避免后续变量冲突 declare +n arr done
方案2:使用 eval 实现兼容旧版本 Bash
如果需要适配低于4.3版本的Bash,可以用eval实现间接取值,注意要确保数组名均为可控的内部值,避免外部不可信输入导致命令注入风险:
a=(1 2) b=(3 4 5 6) c=(7 8 9) z=(a b c) for i in "${z[@]}" do # 用 eval 把对应数组的元素赋值给临时数组 elements eval "elements=(\${${i}[@]})" for j in "${elements[@]}" do echo "数组 $i 的元素:$j" done done
注意事项
- 数组遍历优先使用
"${数组名[@]}"格式,该格式可以正确保留带空格的元素,${数组名[*]}会把所有元素拼接为单个字符串后按分隔符拆分,容易出现异常。 - 优先选择 nameref 方案,避免 eval 带来的安全隐患和语法歧义。
内容的提问来源于stack exchange,提问作者asx123
相关产品推荐
相关产品推荐

