2014-03-04 34 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