如何获得一个变量值,如果变量名存储为字符串?

我怎么能检索一个bash变量值,如果我有变量名作为字符串?

var1="this is real value"
一个=“var1"
通过变量a得到变量1的值。
< /代码> < / pre > < / p >

背景:

我有一些AMI (亚马逊机器图像),我想启动每个AMI的几个实例。一旦它们完成引导,我希望根据其AMI类型设置每个实例。我不想在任何AMI中烘焙大量的脚本或密钥,所以我准备了一个通用的启动脚本,并将其放在S3上,并带有一个公共可访问的链接。在rc。在本地,我放了一小段代码来获取启动脚本并执行它。这是我在ami的全部资料。然后,每个AMI访问一个适用于所有AMI的公共配置脚本和每个AMI的特殊设置脚本。这些脚本是私有的,需要一个经过签名的URL来访问它们。

所以现在,当我触发一个AMI (my_private_ami_1)的实例时,我为S3上呈现的另一个文件传递了一个有签名的URL,该文件包含了所有私有脚本的有签名的URL,以键/值对的形式。 my_private_ami_1 =“http://s3.amazo.../ami_1?signature" ... < /代码> < / >之前 当启动脚本运行时,它下载上面的文件和source。然后它检查AMI类型并为自己选择正确的安装脚本
ami\_type=GET AMI TYPE #ex: sets ami\_type to my\_private\_ami\_1
setup\_url=GET THE SETUP FILE URL BASED ON AMI\_TYPE # this is where this problem arises

所以现在我可以有一个泛型代码,它可以触发实例,而不管它们的AMI类型和实例可以照顾自己。

144850 次浏览

修改了我的搜索关键词,得到了它:)。谢谢你的时间。

你可以使用${!a}:

var1="this is the real value"
a="var1"
echo "${!a}" # outputs 'this is the real value'

这是一个间接参数扩展的例子:

参数展开的基本形式是${parameter}。的价值

. parameter被替换 如果parameter的第一个字符是感叹号(!),则它 引入一个变量间接级别。的值 变量由parameter的其余部分组成,作为 变量;然后展开此变量,并将该值用于 替换的其余部分,而不是parameter本身的值
X=foo
Y=X
eval "Z=\$$Y"

Z设置为foo

现代shell已经支持数组(甚至关联数组)。所以请使用它们,少用eval。

var1="this is the real value"
array=("$var1")
# or array[0]="$var1"

然后当你想调用它时,echo ${array[0]}

对于我的zsh用户,完成与接受的答案相同的事情的方法是使用:

echo ${(P)a} # outputs 'this is the real value'

它被适当地称为参数名称替换

强制将参数名的值解释为a 进一步的参数名称,将在适当的地方使用其值。 请注意,用一个排版命令家族(in 特殊大小写转换)不应用于name的值

.

.

如果与嵌套参数或命令替换一起使用,则 它将以同样的方式作为参数名。例如, 如果你有' foo=bar '和' bar=baz ',字符串${(P)foo}, $ {(P) $ {foo}},和$ {(P) $ (echo bar)}将扩展到巴兹。< / P > 类似地,如果引用本身嵌套,则带有 标志将被视为直接由参数名替换。 如果这个嵌套替换产生一个包含更多的数组,则会出错 不止一个词。例如,如果参数协会“name =协会” 是一个关联数组,那么' ${${(P)name}[elt]} '指的是

.下标为' elt '的关联元素

基于答案:https://unix.stackexchange.com/a/111627

###############################################################################
# Summary: Returns the value of a variable given it's name as a string.
# Required Positional Argument:
#   variable_name - The name of the variable to return the value of
# Returns: The value if variable exists; otherwise, empty string ("").
###############################################################################
get_value_of()
{
variable_name=$1
variable_value=""
if set | grep -q "^$variable_name="; then
eval variable_value="\$$variable_name"
fi
echo "$variable_value"
}


test=123
get_value_of test
# 123
test="\$(echo \"something nasty\")"
get_value_of test
# $(echo "something nasty")

数组也有同样的问题,如果你也在操作数组,下面是如何做到这一点:

array_name="ARRAY_NAME"
ARRAY_NAME=("Val0" "Val1" "Val2")


ARRAY=$array_name[@]
echo "ARRAY=${ARRAY}"
ARRAY=("${!ARRAY}")
echo "ARRAY=${ARRAY[@]}"
echo "ARRAY[0]=${ARRAY[0]}"
echo "ARRAY[1]=${ARRAY[1]}"
echo "ARRAY[2]=${ARRAY[2]}"

这将输出:

ARRAY=ARRAY_NAME[@]
ARRAY=Val0 Val1 Val2
ARRAY[0]=Val0
ARRAY[1]=Val1
ARRAY[2]=Val2

在bash 4.3中,引入了对set变量的'-v'测试。同时,添加了'nameref'声明。这两个特性与间接操作符(!)一起可以实现前面示例的简化版本:

get_value()
{
declare -n var_name=$1
if [[ -v var_name ]]
then
echo "${var_name}"
else
echo "variable with name <${!var_name}> is not set"
fi
}


test=123
get_value test
123


test="\$(echo \"something nasty\")"
get_value test
$(echo "something nasty")


unset test
get_value test
variable with name <test> is not set
由于这种方法消除了对“eval”的需要,因此更安全。 此代码在bash 5.0.3(1)下检查

在bash 4.3+中,你可以使用declare -n:

#!/usr/bin/env bash


var="this is the real value"
var_name="var"


declare -n var_ref=$var_name
echo "${var_ref}"
VALUE=$(eval "echo \$$SOME_VAR_NAME")

例子

SSH_KEY_FILE_PATH_FOO="/tmp/key"
SSH_KEY_FILE_PATH_VAR_NAME_PREFIX="SSH_KEY_FILE_PATH"
SSH_KEY_FILE_PATH_VAR_NAME_SUFFIX="FOO"
SSH_KEY_FILE_PATH=$(eval "echo \$${SSH_KEY_FILE_PATH_VAR_NAME_PREFIX}_${SSH_KEY_FILE_PATH_VAR_NAME_SUFFIX}")
echo "$SSH_KEY_FILE_PATH"
/tmp/key