如果我将变量名称作为字符串,如何检索bash变量值?
var1="this is the real value"
a="var1"
Do something to get value of var1 just using variable a.
我有一些AMI(Amazon Machine Image),我想点开每个AMI的几个实例。一旦完成启动,我想根据其AMI类型设置每个实例。我不想在任何AMI中烘焙大量脚本或密钥,因此我准备了一个通用的启动脚本,并将其放在S3上,并提供可公开访问的链接。在rc.local中,我放了一小段代码来获取启动脚本并执行它。这就是我在AMI中所拥有的一切。然后,每个AMI访问一个通用配置脚本,该脚本适用于所有AMI和每个AMI的特殊设置脚本。这些脚本是私有的,需要签名URL才能访问它们。
现在,当我触发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
为它。然后它检查其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类型和实例可以自己处理。
答案 0 :(得分:190)
您可以使用${!a}
:
var1="this is the real value"
a="var1"
echo "${!a}" # outputs 'this is the real value'
这是间接parameter expansion:
的示例参数扩展的基本形式是
${parameter}
。的价值parameter
已被替换。如果
parameter
的第一个字符是感叹号(!),那么 引入了一个变量间接层。 Bash使用的值 变量由parameter
的其余部分组成,作为 变量;然后展开此变量,并在该变量中使用该值 替换的其余部分,而不是parameter
本身的值。
答案 1 :(得分:24)
X=foo
Y=X
eval "Z=\$$Y"
将Z设为“foo”
使用eval
小心,因为这可能允许通过${Y}
中的值实际执行代码。这可能会通过代码注入造成伤害。
例如
Y="\`touch /tmp/eval-is-evil\`"
会创建/tmp/eval-is-evil
。当然,这也可能是一些rm -rf /
。
答案 2 :(得分:8)
修改了我的搜索关键字并获得了它:)。
eval a=\$$a
感谢您的时间。
答案 3 :(得分:4)
对于我的zsh用户来说,完成与接受的答案相同的方法是使用:
${(P)a}
它被称为Parameter name replacement
这会强制将参数名称的值解释为a 进一步的参数名称,其值将在适当的地方使用。 请注意,使用其中一个排版命令系列设置标志(in 特殊情况转换)不适用于name的值 以这种方式使用。
如果与嵌套参数或命令替换一起使用,则结果为 它将以相同的方式作为参数名称。例如, 如果你有'foo = bar'和'bar = baz',字符串$ {(P)foo}, $ {(P)$ {foo}}和$ {(P)$(echo bar)}将扩展为'baz'。
同样,如果引用本身是嵌套的,则表达式为 flag被视为直接替换为参数名称。 如果此嵌套替换产生的数组更多,则会出错 不止一个字。例如,如果'name = assoc',则参数assoc 是一个关联数组,然后'$ {$ {(P)name} [elt]}'指的是 关联下标'elt'的元素。
答案 4 :(得分:1)
数组也有同样的问题,如果您也要操纵数组,这是怎么做:
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
答案 5 :(得分:1)
在bash 4.3中,引入了对设置变量的'-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
由于这种方法消除了对“评估”的需求,因此更加安全。 此代码在bash 5.0.3(1)下进行了检查。
答案 6 :(得分:0)
现代shell已经支持数组(甚至是关联数组)。所以请使用它们,少用eval。
var1="this is the real value"
array=("$var1")
# or array[0]="$var1"
然后当你想调用它时,回显$ {array [0]}
答案 7 :(得分:0)
根据答案:https://unix.stackexchange.com/a/111627
def solution(prices: Array[Int]): Int = {
prices.foldLeft((prices.headOption.getOrElse(0), 0: Int)) { (tuple, price) =>
(Math.min(tuple._1, price), Math.max(tuple._2, price - tuple._1))
}._2
}