2

Hey trying to pass an array to my Bash script and echo both the key and value, but key is being echoed as an int, could any explain why :-)

script:

#!/bin/bash
string=$1 && shift
array=($@)

for i in "${!array[@]}"
do
  echo "key  :" $i
  echo "value:" ${array[$i]}
done

running script:

:~$ declare -A arr
:~$ arr["key1"]=Value1
:~$ ./test.sh bar ${arr[@]}
    key  : 0
    value: value1

Also why do i need to do this line (string=$1 $$ shift) found this in some other thread, but not sure i understand why, cant first parameter be the array?

2 Answers 2

4

You aren't passing an array; you are only passing the values stored in the array. In fact, you cannot pass the array as a whole, because there is no such thing as an array value in shell, just names with an array attribute set.

To do what you want, you have to use the array as a global variable, which means you can only do this with a function, not a script. Also, while it might be possible to do using indirect parameter expansion alone, it's far simpler to do using namerefs (requiring bash 4.3 or later):

foo () {
    declare -n a=$1
    for key in "${!a[@]}"; do
       echo "key: $key"
       echo "value: ${a[$key]}"
    done
}

Note that you'll get a circular name reference error, though, if the internal array name set by the declare command is the same as the global you are trying to pass; caveat emptor.


To create a series of alternating keys and values to pass as separate arguments, use a regular array.

declare -A arr
arr[romeo]="John Doe"
arr[juliet]="Jane Smith"
kvpairs=()
for k in "${!arr[@]}"; do
    kvpairs+=( "$k" "${arr[$k]}" )
done
./test.sh "${kvpairs[@]}"

(Note: I don't recall if the array keys are stored or iterated in any particular order; assume they are not.)

Inside test.sh, you can reconstruct the array:

declare -A arr
while (( $# > 0 )); do
  arr["$1"]="$2"
  shift 2
done
Sign up to request clarification or add additional context in comments.

7 Comments

hmm, how would i then go about passing a set of users, each with a specific value associated to them? can i only pass strings and ints? thx for help
bash has exactly one data type: the string. Even ints are just strings that are treated specially in certain contexts. Also, the API for calling a program only allows for passing strings as arguments. The only way to pass the data you want is as a series of separate arguments: ./test.sh alice 5 bob 9 charlie 2.
arghh :-) but ok it will work, an might be easier for me as these parameters are coming from an Azure template, thx
now i just need to figure out how i do a for loop with these parameters.
And unfortunately, bash doesn't provide a way to expand an associative array to an alternating list of keys and values (or I'm forgetting it); I'll add a workaround to the answer.
|
0

First of all shift is used to shift the position of arguments by 1, so that the value of $1 will be transferred to $0 and so on. This is done because arrays start from position 0 in bash.

Next, instead of using $i to print the index position, use ${!i} instead. This will print the index name instead of index position number.

1 Comment

not working :-( insted it now writes values instead of keys.

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.