2014-03-04 69 views
3

我想通過使用函數來發生6次事情來整理我的bash腳本之一。該腳本從config.ini文件中設置了許多變量,然後列出它們並要求確認用戶希望繼續使用這些預定義的值。如果沒有,則逐步通過每個變量並要求輸入新的變量(或將其保留爲空並按回車鍵以使用預定義的值)。這段代碼可以完成該操作:在bash中間接引用,爲什麼這不起作用?

echo Current output folder: $OUTPUT_FOLDER 
echo -n "Enter new output folder: " 
read C_OUTPUT_FOLDER 
if [ -n "$C_OUTPUT_FOLDER" ]; then OUTPUT_FOLDER=$C_OUTPUT_FOLDER; fi 

的想法是設置$OUTPUT_FOLDER$C_OUTPUT_FOLDER價值,但只有當$C_OUTPUT_FOLDER不爲空。如果$C_OUTPUT_FOLDER爲空,它將不會執行任何操作並將$OUTPUT_FOLDER保留爲稍後在腳本中使用的狀態。

有6個變量是從config.ini中設置的,所以此塊當前重複6次。我做了一個功能new_config()主要內容如下:

new_config() { 
    echo Current $1: ${!2} 
    echo -n "Enter new $1: " 
    read $3 
    if [ -n "${!3}" ]; then $2=${!3}; fi 
} 

我與調用它(在這種情況下):

new_config "output folder" OUTPUT_FOLDER C_OUTPUT_FOLDER 

當我運行該腳本,它在一個錯誤if line:

./test.sh: line 9: OUTPUT_FOLDER=blah: command not found 

那麼,什麼給了?腳本中的代碼塊可以正常工作,並且(在我相當新穎的眼中),函數應該完全一樣。

在此先感謝任何指針。

+0

不確定你要做什麼,但問題出在'$ 2 = $ {!3}'。 – devnull

+0

是的,我想了很多,謝謝。我不明白爲什麼它會引用變量,所以'$ 2 = $ {!3}'擴展爲'OUTPUT_FOLDER = $ C_OUTPUT_FOLDER'(因爲錯誤提到了'OUTPUT_FOLDER = blah',「blah」就是我輸入的內容作爲新的輸出文件夾),但然後拋出這個錯誤。我想讓用戶有機會在每次運行時更改腳本中的任何預定義變量(無需直接編輯config.ini文件)。因此,如果他們輸入一個新值,請將'$ OUTPUT_FOLDER'設置爲它,否則(如果$ C_OUTPUT_FOLDER爲空)則保留ini文件中定義的$ OUTPUT_FOLDER。 – user3370369

回答

0

問題是,bash將命令拆分爲令牌之前的變量替換,請參見http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_01_04.html#sect_01_04_01_01。特別是POSIX shell的規則使分配成爲標記化的特例:"If all the characters preceding '=' form a valid name (see XBD Name), the token ASSIGNMENT_WORD shall be returned." - 它是觸發分配路徑的ASSIGNMENT_WORD標記。它不會在變量替換之後重複標記,這就是爲什麼您的代碼無法工作。

你可以得到你的代碼,像這樣的工作:

new_config() { 
    echo Current $1: ${!2} 
    echo -n "Enter new $1: " 
    read $3 
    if [[ -n "${!3}" ]]; then echo setting "$2='${!3}'"; eval "$2='${!3}'"; fi 
} 

new_config "output folder" OUTPUT_FOLDER C_OUTPUT_FOLDER 
echo $OUTPUT_FOLDER 

由於@chepner指出的那樣,你可以使用declare -g $2="${!3}"而不是EVAL這裏,並在新的bash版本,這是一個更好的答案。不幸的是declare -g需要bash 4.2,儘管這已經是3年了,但它仍然不是無處不在 - 例如,OS X Mavericks停留在3.2.51。

+0

工程就像一個魅力,謝謝你!初學者的bash指南也非常有用。 – user3370369

+1

使用'declare'而不是'eval'。您無需實際評估任何代碼;您只需在分配前擴大「$ 2」和「$ 3」的值(間接)即可。 – chepner

+0

我會編輯它,但實際的等價物(declare -g)需要最近的bash(令人驚訝的是,OSX仍在使用2007年的一個)。 – bazzargh