Reputation: 1802
I want to be able to do:
declare -A map=(
['A']=1
['B']=2
['C']=3
['D']=4
)
sh script2.sh ???
params = ...
echo ${params['A']}
ie, access parameters by keys. I have seen related questions for normal arrays and the answer to them has been to pass the array as:
sh script2.sh "${AR[@]}"
which I believe translates to:
sh script2.sh "${map[0]}" "${map[1]}" "${map[2]}"
But with that, I can only access the elements based on their order.
Is there a clever trick to achieve what I want? perhaps with something that passes on "A=1" "B=2" "C=3" "D=4"
instead and have script2.sh
parse them? or is there a neater solution?
Upvotes: 1
Views: 1222
Reputation: 15358
If you are only calling script2.sh
from inside script1.sh
, then all you need to do (as @markp-fuso pointed out) is source script2.sh
and it will run in the current context with all the data already loaded.
If you really want it to be on the command line, then pass it as key=val
and have your code in script2.sh
check each of it's args for that format and set them in an associative array.
declare -A map=()
for arg in "$@"
do if [[ "$arg" =~ ^[A-Z]=[0-9]$ ]] # more complex k/v will get ugly
then map[${arg/=?}]=${arg/?=} # as will the assignment w/o eval
fi
done
# And finally, just to see what got loaded -
declare -p map
$: script2.sh C=3 A=1
declare -A map=([A]="1" [C]="3" )
As mentioned above, a more complicated possible set of key names and/or values will require a suitably more complex test as well as assignment logic. Clearly, for anything but the simplest cases, this is going to quickly get problematic.
Even better, set up a full getopts
loop, and pass your args with proper indicators. This takes more design and more implementation, but that's what it takes to get more functionality.
Upvotes: 3
Reputation: 34808
Assumptions:
script2
(this could be relaxed but would likely require adding some option flag processing to script2
)map
(could probably make this dynamic but that's for another day)script2
gets mucho complicated really quick (there are likely some workarounds for this scenario, too)Some basic components:
The array named map
:
$ declare -A map=(
['A']=1
['B']=2
['C']=3
['D']=4
)
Use typeset
to generate a command to (re)produce the contents of array map
:
$ typeset -p map
declare -A map=([A]="1" [B]="2" [C]="3" [D]="4" )
From here we can pass the typeset
output to script2
and then have script2
eval
uate the input, eg:
$ cat script1
echo "in script1"
declare -A map=(
['A']=1
['B']=2
['C']=3
['D']=4
)
./script2 $(typeset -p map)
$ cat script2
echo "in script2"
echo " \$@ = $@"
eval "$@"
for i in "${!map[@]}"
do
echo "${i} : ${map[${i}]}"
done
Running script1
generates:
$ ./script1
in script1
in script2
$@ = declare -A map=([A]="1" [B]="2" [C]="3" [D]="4" )
A : 1
B : 2
C : 3
D : 4
I know, I know, I know ... eval
== evil. I'll have to think about a replacement for eval
... also open to suggestions.
Upvotes: 2