是否可以用shell脚本打印变量的内容? (间接引用)

是否可以用shell脚本打印变量的内容? (间接引用)

假设我声明了以下变量:

$ 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

3.5.3 Shell参数扩展

答案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 的回答,但使用名称引用变量而不是变量间接寻址(需要bash4.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

为了完整起见,使用关联数组(在bash4.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)都有evalshell 代码评估,因此重要的是内容$var应在您的控制范围内,否则可能会成为任意命令注入漏洞(与${!var}方法相同)。

相关内容