假设我声明了以下变量:
$ var='$test'
$ test="my string"
如果我打印它们的内容,我会看到以下内容:
$ echo $var
$test
$ echo $test
my string
我想找到一种方法来打印内容的内容$var
(即内容$test
)。所以我尝试执行以下操作:
$ echo $(echo $var)
$test
但这里的结果$test
不是"my string"
......是否可以使用bash打印变量内容的内容?
答案1
您可以使用 bash 的间接变量扩展来完成此操作(只要您可以省略$
引用变量中的 ):
$ var=test
$ test="my string"
$ echo "$var"
test
$ echo "${!var}"
my string
答案2
var
对于其中包含的变量名以前缀开头的情况,$
您可以使用eval
:
$ var='$test'
$ test="my string"
$ eval echo $var
my string
这里发生了什么:
- bash 扩展
$var
为 value$test
,生成eval echo $test
命令; eval
评估echo $test
表达式并产生所需的结果。
请注意,一般情况下使用eval
可能是危险的(取决于 中存储的内容var
),因此最好避免使用它。间接扩展功能更适合您的情况(但您需要摆脱$
登录$test
)。
答案3
如同Jesse_b 的回答,但使用名称引用变量而不是变量间接寻址(需要bash
4.3+):
$ declare -n var=test
$ test="my string"
$ echo "$var"
my string
名称引用变量var
保存其引用的变量的名称。当变量被取消引用为 时$var
,将返回其他变量的值。
bash
递归解析名称引用:
$ declare -n var1=var2
$ declare -n var2=test
$ test="hello world"
$ echo "$var1"
hello world
为了完整起见,使用关联数组(在bash
4.0+ 中)也是解决此问题的一种方法,具体取决于要求:
$ declare -A strings
$ strings[test]="my string"
$ var=test
$ echo "${strings[$var]}"
my string
这提供了一种通过可以动态确定的键或名称来访问多个值的更灵活的方式。如果您想在单个数组中收集特定类别的所有值,但仍然能够通过某个键访问它们(例如通过 ID 访问的名称,或通过目的访问的路径名等),这可能是更好的选择,因为它不会污染脚本的变量命名空间。
答案4
和zsh
:
$ var='$test'
$ test='*'
$ printf '%s\n' ${(e)var}
*
使用任何类似 Bourne 的 shell
$ eval 'printf "%s\n" "'"$var"'"'
*
请记住,在这些 shell 中,必须引用变量扩展以防止 split+glob(zsh
例外),并且echo
不能用于任意数据。
由于两者(e)
都有eval
shell 代码评估,因此重要的是内容$var
应在您的控制范围内,否则可能会成为任意命令注入漏洞(与${!var}
方法相同)。