string 如果变量名存储为字符串,如何获取变量值?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1921279/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get a variable value if variable name is stored as string?
提问by bhups
How can I retrieve a bash variable value if I have the variable name as string?
如果我将变量名称作为字符串,如何检索 bash 变量值?
var1="this is the real value"
a="var1"
Do something to get value of var1 just using variable a.
Context:
语境:
I have some AMI's (Amazon Machine Image) and I want to fire up a few instances of each AMI. As soon as they finish booting, I want to setup each instance according to its AMI type. I don't want to bake lots of scripts or secret keys inside any AMI so I prepared a generalized startup script and I put it on S3with a publicly accessible link. In rc.local I put small piece of code which fetches the startup script and executes it. This is all I have in the AMIs. Then each AMI accesses a common configuration script which is applicable to all AMIs and special setup scripts for each. These scripts are private and require a signed URL to access them.
我有一些 AMI(亚马逊机器映像),我想启动每个 AMI 的几个实例。一旦他们完成启动,我想根据其 AMI 类型设置每个实例。我不想在任何 AMI 中烘焙大量脚本或密钥,所以我准备了一个通用的启动脚本,并将它放在S3 上,并提供一个可公开访问的链接。在 rc.local 中,我放了一小段代码来获取启动脚本并执行它。这就是我在 AMI 中的全部内容。然后每个 AMI 访问一个通用配置脚本,该脚本适用于所有 AMI 和每个 AMI 的特殊设置脚本。这些脚本是私有的,需要一个签名的 URL 才能访问它们。
So now, when I fire an instance of an AMI (my_private_ami_1), I pass a signed URL for one more file presented on S3 which contains signed URL for all private scripts in terms of key/value pair.
所以现在,当我触发一个 AMI 实例 (my_private_ami_1) 时,我会为 S3 上显示的另一个文件传递一个签名 URL,该文件包含所有私有脚本在键/值对方面的签名 URL。
config_url="http://s3.amazo.../config?signature"
my_private_ami_1="http://s3.amazo.../ami_1?signature"
...
当启动脚本运行时,它会下载上面的文件,然后source
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
So now I can have a generic code which can fire instances irrespective of their AMI types and instances can take care of themselves.
所以现在我可以有一个通用代码,它可以触发实例而不管它们的 AMI 类型如何,并且实例可以自行处理。
回答by Phil Ross
You can use ${!a}
:
您可以使用${!a}
:
var1="this is the real value"
a="var1"
echo "${!a}" # outputs 'this is the real value'
This is an example of indirect parameter expansion:
这是间接参数扩展的示例:
The basic form of parameter expansion is
${parameter}
. The value ofparameter
is substituted.If the first character of
parameter
is an exclamation point (!), it introduces a level of variable indirection. Bash uses the value of the variable formed from the rest ofparameter
as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value ofparameter
itself.
参数展开的基本形式是
${parameter}
. 的值parameter
被替换。如果的第一个字符
parameter
是感叹号 (!),则它引入了一个变量间接级别。Bash 使用由其余部分组成的变量的值作为变量parameter
的名称;然后扩展这个变量,并且该值用于替换的其余部分,而不是parameter
它本身的值。
回答by bhups
X=foo
Y=X
eval "Z=$$Y"
sets Z to "foo"
将 Z 设置为“foo”
Take careusing eval
since this may allow accidential excution of code through values in ${Y}
. This may cause harm through code injection.
请小心使用,eval
因为这可能允许通过${Y}
. 这可能会通过代码注入造成危害。
For example
例如
Y="\`touch /tmp/eval-is-evil\`"
would create /tmp/eval-is-evil
. This could also be some rm -rf /
, of course.
会创建/tmp/eval-is-evil
. rm -rf /
当然,这也可能是一些。
回答by bhups
Modified my search keywords and Got it :).
修改了我的搜索关键字,明白了:)。
eval a=$$a
谢谢你的时间。回答by smac89
For my fellow zsh users, the way to accomplish the same thing as the accepted answer is to use:
对于我的 zsh 用户,完成与接受的答案相同的事情的方法是使用:
${(P)a}
${(P)a}
It is called Parameter name replacement
这叫做参数名替换
This forces the value of the parameter name to be interpreted as a further parameter name, whose value will be used where appropriate. Note that flags set with one of the typeset family of commands (in particular case transformations) are not applied to the value of name used in this fashion.
If used with a nested parameter or command substitution, the result of that will be taken as a parameter name in the same way. For example, if you have ‘foo=bar' and ‘bar=baz', the strings ${(P)foo}, ${(P)${foo}}, and ${(P)$(echo bar)} will be expanded to ‘baz'.
Likewise, if the reference is itself nested, the expression with the flag is treated as if it were directly replaced by the parameter name. It is an error if this nested substitution produces an array with more than one word. For example, if ‘name=assoc' where the parameter assoc is an associative array, then ‘${${(P)name}[elt]}' refers to the element of the associative subscripted ‘elt'.
这会强制将参数名称的值解释为进一步的参数名称,其值将在适当的地方使用。请注意,使用排版命令系列(特别是转换)之一设置的标志不适用于以这种方式使用的 name 值。
如果与嵌套参数或命令替换一起使用,其结果将以相同的方式作为参数名称。例如,如果您有 'foo=bar' 和 'bar=baz',则字符串 ${(P)foo}、${(P)${foo}} 和 ${(P)$(echo bar) } 将扩展为'baz'。
同样,如果引用本身是嵌套的,则将带有标志的表达式视为直接由参数名称替换。如果此嵌套替换产生一个包含多个单词的数组,则这是一个错误。例如,如果 'name=assoc' 其中参数 assoc 是关联数组,则 '${${(P)name}[elt]}' 指的是关联下标的元素 'elt'。
回答by VFein
Based on the answer: https://unix.stackexchange.com/a/111627
基于答案: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=
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")
回答by Alexandre Hamon
Had the same issue with arrays, here is how to do it if you're manipulating arrays too :
数组也有同样的问题,如果你也在操作数组,这里是如何做到的:
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]}"
This will output :
这将输出:
ARRAY=ARRAY_NAME[@]
ARRAY=Val0 Val1 Val2
ARRAY[0]=Val0
ARRAY[1]=Val1
ARRAY[2]=Val2
回答by ghostdog74
modern shells already support arrays( and even associative arrays). So please do use them, and use less of eval.
现代 shell 已经支持数组(甚至关联数组)。所以请务必使用它们,并少使用 eval。
var1="this is the real value"
array=("$var1")
# or array[0]="$var1"
then when you want to call it , echo ${array[0]}
然后当你想调用它时,echo ${array[0]}