linux shell中实现变量间接引用的核心是${!var}语法,即用变量值作为另一变量名再取其值,支持动态变量名和组合拼接,安全高效;eval方式虽兼容旧版但有注入风险。

Linux Shell 中实现变量间的间接引用,核心是:用一个变量的值作为另一个变量的名字,再取那个“名字变量”的值。本质是“变量名动态化”,不写死,靠运行时决定。
用 ${!var} 语法最简洁安全
这是 Bash 4.0+ 原生支持的方式,推荐优先使用。它直接解析变量名字符串,不经过命令执行,无注入风险。
- 假设 name="Alice",ref="name"
- 那么 ${!ref} 就等价于 $name,结果是 Alice
- 支持组合变量名,比如:prefix="user"; suffix="1"; varname="${prefix}_${suffix}" → 得到 user_1;再用 ${!varname} 取 $user_1 的值
用 eval 需谨慎但兼容性好
适用于老版本 Bash 或需要更灵活拼接场景,但要注意 shell 解析顺序和安全性。
- 同样设 name="Alice",ref="name"
- 写 eval "echo \$$ref" 或 eval "val=\$$ref"; echo "$val"
- 原理是让 shell 二次展开:先展开 $ref 得 name,再加 $ 变成 $name,最后求值
- ⚠️ 注意:如果 $ref 内容来自用户输入或文件,可能引发命令注入,务必校验或避免使用
实际常用场景举例
比如管理多个学生信息,用编号前缀统一命名:
- S01_name="Li Hao"; S01_dept="Computer"; S02_name="Zhang Ju"
- 用户选了 stunum="S01",构造变量名:name_var="${stunum}_name"
- 取值只需:echo "${!name_var}" → 输出 Li Hao
- 同理可取 ${!${stunum}_dept}(注意要写成 ${!dept_var},不能嵌套展开)
注意事项
间接引用不是万能的,有些情况会失效或行为异常:
- 不能用于带通配符的变量名,比如 files="*",${!files} 会把 * 展开为当前目录所有文件名,不再是字面量 *
- 数组、关联数组的间接引用需额外处理,${!arr[@]} 是取键名列表,不是间接取值
- 环境变量(如 PATH)可用 ${!var} 引用,但修改需用 export 显式赋值











