2017-03-22 47 views
1
我有以下的bash文件

从功能装载我作为配置中使用:配置文件在bash

# config 
servers=(
    [vagrant.host]=192.168.20.20 
    [vagrant.port]=22 
    [vagrant.user]=ubuntu 
    [vagrant.identity]=~/.ssh/id_rsa 
    [vagrant.cwd]=/home/ubuntu/website 
) 

,我使用从我的主脚本加载:

declare -A servers 
. config 

echo "${servers["vagrant.host"]}" # prints 192.168.20.20 

如果该代码不在一个很好的功能,但我不需要总是加载配置文件,我把加载代码放在一个函数中。当我调用如下所示的函数时,我收到一个错误。

function loadConfig { 
    declare -A servers 
    . config 
} 

loadConfig 

echo "${servers["vagrant.host"]}" 
# vagrant.host: syntax error: invalid arithmetic operator (error token is ".host") 

我不知道什么是导致错误,谷歌没有帮助。

回答

2

关联数组当地范围默认情况下,使全球在Shell功能,使用时加入-g标志

declare -Ag servers 

The declare builtin command

-g 创建全球变量;否则将被忽略(默认情况下,声明宣称当地范围内的变量在shell函数中使用时)

在调试模式显而易见的脚本运行相同的脚本,制作我这个,

$ bash -x mainscript.sh 
+ loadConfig 
+ declare -Ag servers 
+ . config 
++ servers=([vagrant.host]=192.168.20.20 [vagrant.port]=22 [vagrant.user]=ubuntu [vagrant.identity]=~/.ssh/id_rsa [vagrant.cwd]=/home/ubuntu/website) 
+ echo 192.168.20.20 
192.168.20.20 
1

使用declare -g是直截了当,容易。

但它也造成全球变量的污染。在此情况下,你要使用你的config,不想全局变量,你可以在函数调用定义变量,如:

function loadConfig { 
    declare -n main="$1" # needs bash 4.3 - create an reference to indirect name 
    declare -A servers  # the array name used in the config (local only) 
    . ./conf 
    # copy the array to indrectly aliased array... 
    for key in "${!servers[@]}" 
    do 
     main["$key"]="${servers["$key"]}" 
    done 
} 

#MAIN 
declare -A currservers #declare your current array 
loadConfig currservers #pass its name to loadConfig 

echo "${currservers['vagrant.host']}" 
# 192.168.20.20 

不幸的是,这需要合理的新版本bash4.3+

+0

用于演示'declare -n'方法的'++'! – Inian

+0

Bash 4.3不是一个选项,最近我发现macOS会与bash 3.2一起出现,并且我转而使用扁平变量来支持它。 –

+1

@IvanDokov这对你的真实项目没关系。从纯粹的问题的角度来看(例如在函数中采用assoc数组),这是一个可行的解决方案。 – jm666