0

I am trying to read a string into an associative array.

The string is being properly escaped and read into .sh file:

./myScript.sh "[\"el1\"]=\"val1\" [\"el2\"]=\"val2\""

within the script

#!/bin/bash -e
declare -A myArr=( "${1}" ) #it doesn't work either with or without quotes

All I get is:

line 2: myArr: "${1}": must use subscript when assigning associative array

Googling the error only results in "your array is not properly formatted" results.

3
  • 1
    Please try: declare -A "myArr=( ${1} )" Commented Mar 8, 2021 at 23:28
  • Like using eval this is likely to produce code injection or other bugs when dealing with complex inputs. Commented Mar 9, 2021 at 1:09
  • Would you be OK with something like ./myScript.sh el1 val1 el2 val2? Commented Mar 9, 2021 at 1:10

3 Answers 3

3

You could read key/value pairs from variable inputs in series:

$ cat > example.bash <<'EOF'
#!/usr/bin/env bash

declare -A key_values
while true
do
    key_values+=(["$1"]="$2")
    shift 2
    if [[ $# -eq 0 ]]
    then
        break
    fi
done

for key in "${!key_values[@]}"
do
    echo "${key} = ${key_values[$key]}"
done
EOF
$ chmod u+x example.bash
$ ./example.bash el1 val1 el2 val2
el2 = val2
el1 = val1

This should be safe no matter what the keys and values are.

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

Comments

1

Instead of caring about proper double escaping, set the variables on caller side, and use bash declare -p. That way you will always get properly escaped string.

declare -A temp=([el1]=val1 [el2]=val2)
./script.sh "$(declare -p temp)"

Then do:

# ./script.sh
# a safer version of `eval "$1"`
declare -A myarr="${1#*=}"

Comments

0

solution:

./test.sh "( [\"el1\"]=\"val1\" [\"el2\"]=\"val2\" )"

and within the script:

#!/bin/bash -e

declare -A myArr="${1}"
declare -p myArr

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

Returns:

> ./test.sh "( [\"el1\"]=\"val1\" [\"el2\"]=\"val2\" )"
declare -A myArr=([el2]="val2" [el1]="val1" )
key  : el2
value: val2
key  : el1
value: val1

I can't explain why this works, or why the order changes though.

Test it yourself here

3 Comments

This doesn't work in my testing; it creates a single array element (indexed by "0") containing the entire argument as a literal string. Add declare -p myArr at the end to see what's actually happening.
@GordonDavisson it works for me perfectly - what is your issue? also improved on answer, you can see the output of declare -p myArr
Ah, I see, I was testing it without supplying the outer parentheses in the argument (I just copied the argument format from the original question). With parens, it works for me too.

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.