2009-11-07 65 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