1

I want to pass associate array as a single argument to shell script.

mainshellscript.sh :

#!/bin/bash
declare -A cmdOptions=( [branch]=testing [directory]=someDir [function1key]=function1value [function1key]=function1value )
./anothershellscript.sh cmdOptions

anothershellscript.sh :

#!/bin/bash
#--- first approach, didn't work, shows error "declare: : not found"
#opts=$(declare -p "$1")
#declare -A optsArr=${opts#*=}
#---
# second approach, didnt work, output - declare -A optsArr=([0]="" )
#declare -A newArr="${1#*=}"
#declare -p newArr
#---

I'm suspecting that they way I am collecting array in anothershellscript.sh is wrong, I'm finding a way to access map values simply by providing echo "${optsArr[branch]}" shall give testing.

I am using bash version 4.4.23(1)-release (x86_64-pc-msys).

1
  • Is "anotherscript" something you can source rather then execute? Commented Dec 17, 2020 at 14:37

3 Answers 3

4

Passing Associative array to sub script

Associative arrays and regular arrays are not well exported. But you could pass variables by using declare -p in some wrapper call.

First script:

#!/bin/bash
declare -A cmdOptions=( [branch]=testing     [function1key]=function1value
                        [directory]=someDir  [function2key]=function2value )
declare -a someArray=( foo "bar baz" )

declare -x someVariable="Foo bar baz"    # Using *export* for simple variables

bash -c "$(declare -p cmdOptions someArray someVariable);. anothershellscript.sh"

Note syntax . anothershellscript.sh could be replaced by source anothershellscript.sh.

Doing so, prevent need of temporary files or temporary variable and keep STDIN/STDOUT free.

Then your anothershellscript.sh could use your variables as is.

#!/bin/bash

declare -p cmdOptions someArray someVariable

could work.

Sign up to request clarification or add additional context in comments.

Comments

4

Processes are separate - they do not share variables. A variable set in one process is not visible in the other process. Except: child processes inherit exported variables, but cmdOptions is not exported and you can't export associative arrays anyway.

So pass the string representation of the array to the child, either via arguments or with a file or with an exported variable:

#!/bin/bash
declare -A cmdOptions=( [branch]=testing [directory]=someDir [function1key]=function1value [function1key]=function1value )

export SOME_VAR="$(declare -p cmdOptions)"              # env or
declare -p cmdOptions > some_file.txt                   # file or
./anothershellscript.sh "$(declare -p cmdOptions)"      # arg
# Note - `declare -p` is called _on parent side_!

Then load in the child:

#!/bin/bash
declare -A newArr="${SOME_VAR#*=}"      # env or
. some_file.txt                         # file or
declare -A newArr="${1#*=}"             # arg

# How to load from file so that current environment is not affected:
tmp=$(
   . some_file.txt
   declare -p cmdOptions
)
declare -A newArr=${tmp#*=}" 

Comments

1

You'll have to rebuild that array in second script, here is an example script1:

#!/bin/bash
declare -A test=(
    [v1]=1
    [v2]=2
    [v3]=3
)

for key in "${!test[@]}"; { data+=" $key=${test[$key]}"; }
echo "$data" | ./test2

script2:

#!/bin/bash
read   -ra data
declare -A test2

for item in "${data[@]}"; {
    key="${item%=*}"
    val="${item#*=}"
    test2[$key]="$val"
}
echo "${test2[@]}"

Comments

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.