2017-03-22 90 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