1

I am having the following bash file which I use as configuration:

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

and I load it from my main script using:

declare -A servers
. config

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

If the code is not in a function it works great, but I don't need the config file always loaded and I put the loading code in a function. When I call the function like shown below I receive an error.

function loadConfig {
    declare -A servers
    . config
}

loadConfig

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

I have no idea what is causing the error and Google didn't help.

0

2 Answers 2

2

Associative arrays are local scope by default, make it global by adding the -g flag

declare -Ag servers

The declare builtin command

-g create global variables when used in a shell function; otherwise ignored (by default, declare declares local scope variables when used in shell functions)

Running the same script with the obvious script in debugger mode, produced me this,

$ 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
Sign up to request clarification or add additional context in comments.

Comments

1

Using the declare -g is straigforward and easy.

But it also causes pollution by global variables. In cases here you want to use your config and don't want global variables, you can define the variable at the function call, like:

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

Unfortunately, this needs reasonable new bash version 4.3+.

3 Comments

++ for demonstrating the declare -n approach!
Bash 4.3 is not an option and recently I found that macOS is coming with bash 3.2 and I moved to flat variables to support it.
@IvanDokov that's ok for your real project. From the pure question's point of view (e.g. sourcing assoc array in the function) it is a working solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.