2009-11-07 62 views
10

比方说,我有一个变量的名字保存在另外一个变量:shell变量,间接

myvar=123 
varname=myvar 

现在,我想只要使用$ varname的变量获得123。 有没有直接的方法呢?我发现内置通过名称查找没有这样的庆典,所以想出了这个:

function var { v="\$$1"; eval "echo "$v; } 

所以

var $varname # gives 123 

看起来并不太坏结束,但我想知道如果我错过了更明显的东西。提前致谢!

+0

这被标记为6年后问的问题的副本?恕我直言,这个问题+答案比联系更清晰。 – inger 2017-09-01 23:30:13

回答

12

man page of bash

${!varname} 

如果参数的第一个字符是一个感叹号,被引入 可变间接层。 Bash使用由其余参数形成的变量的值作为变量的名称; 这个变量然后被展开,并且该值被用于其余的 替换,而不是参数本身的值。这是被称为间接扩展的 。

+0

当然,就是这样。 试图RTFM,但不知何故这种描述: ----------------- $ {!prefix *} $ {!prefix @} 名称匹配前缀。扩展为名称以前缀开头的变量名称,用IFS 特殊变量的第一个字符分隔。当使用@并且扩展出现在双引号内时,每个变量名称将扩展为单独的单词。 ----------------- 并没有让我明显的答案。 干杯! – inger 2009-11-07 20:07:34

+0

@DigitalRoss:问题是标有“bash”,那么为什么你想限制答案POSIX标准? – tangens 2009-11-07 20:10:25

+1

这是一个很好的答案,是的它适用于bash。我想完美的答案会宣布'$ {!varname}',然后记下可移植性问题,以防止操作系统出现问题。 – DigitalRoss 2009-11-07 20:16:11

12

没有直接符合Posix的语法,只有一个bash ism。我经常这样做:

eval t="\$$varname" 

这将工作在任何POSIX Shell的,包括那些系统中bash是登录shell和/bin/sh是一些更小,更快像ash。我喜欢bash并将其用于我的登录shell,但是我避免了命令文件中的bashisms。


注意:编写bash特定脚本时遇到的一个问题是,即使您可以指望安装bash,它也可能位于路径上的任何位置。在这种情况下使用完全一般的/usr/bin/envshebang样式可能是一个好主意,但请注意,这仍然不是100%可移植并且存在安全问题。

+0

根据您需要的值的上下文,您可以使用'$(eval \ $$ varname)'而不是赋值。 – 2009-11-07 20:08:38

+0

尝试了几乎,但错过了它。比矿井更快! – inger 2009-11-07 20:12:03

+0

不是'$(....)'非posix?不应该是'\'eval \ $$ varname' \'而不是? – 2013-07-31 11:51:40

1

${!varname}应该做的伎俩

$ var="content" 
$ myvar=var 
$ echo ${!myvar} 
content 
+0

谢谢,似乎你的答案比tangens晚了一会儿,所以我选择了一个:) – inger 2009-11-07 20:24:33

1

我通常看Advance Bash-Scripting Guide当我需要梳洗我击技能。

关于你的问题看Indirect References

符号是:

Version < 2 
\$$var 

Version >= 2 
${!varname} 
+0

嗯,快速浏览指南 - 显然太快:) 好像我必须通读它正确..感谢提示! – inger 2009-11-07 20:22:32

+0

这是我选择的快速参考,我倾向于比手册页更频繁地使用它。但正如你所说,快速浏览有时是不够的。 – 2009-11-07 20:30:14

+0

一般而言,ABS应该带有大量的盐。虽然这个答案本身没有错。 – tripleee 2016-08-01 06:54:47

0
# bmuSetIndirectVar() 
# TO DOUBLE CHECK THIS COMMENT AND DEMO 
# This function is an helper to read indirect variables. 
# i.e. get the content of a variable whose name is saved 
# within an other variable. Like: 
# MYDIR="/tmp" 
# WHICHDIR="MYDIR" 
#  bmuSetIndirectVar "WHICHDIR" "$MYDIR" 
# 
bmuSetIndirectVar(){ 
    tmpVarName=$1 
    locVarName=$1 
    extVarName=$2 
    #echo "debug Ind Input >$1< >$2<" 
    eval tmpVarName=\$$extVarName 
    #echo "debug Ind Output >$tmpVarName< >$extVarName<" 
    export $locVarName="${tmpVarName}" 
} 
我目前使用的这个小功能

。我对此并不满意,并且我在网上看到了不同的解决方案(如果我能记得我会在这里写下它们),但它似乎有效。在这几行中,已经有一些冗余和额外的数据,但它对调试很有帮助。

如果你想看到它在的地方,也就是在那里,我使用它,请检查: https://github.com/mariotti/bmu/blob/master/bin/backmeup.shellfunctions.sh

当然这不是最好的解决办法,但让我去进行这项工作,在 希望我可以尽快用一些更一般的东西来取代它。

+0

之前的问题;)我不喜欢这个功能是,我使用“eval”,这通常是不良设计的触发器。当然,有些地方你需要它。我喜欢的是使用一个函数,我可以从问题中分离出代码并在以后进行优化。甚至可能引入一个shell版本检查或类似的东西。 – mariotti 2017-03-31 16:13:40