1

i want to use a manual created (fake multidimensinal) array in bash script but when using the array in conditions i want to use the array name from a variable.

Using bash version 4.1.2 so declare -n doesn't exist.

I guess my example will be more helpfull to see what i want to do:

declare -A test
test[ar,action]="dosomething"
test[bc,action2]="doelse"
test[bc,resolv]="dotest"

#works:
echo "this works: ${test[bc,action2]}"

#but if i want to use a variable name, bad substitution error

name="test"
echo "01 this works: ${$name[bc,action2]}"

#another test doesn't work also

echo "02 test2 : ${!name[bc,action2]}"

#final goal is to do something like this:

if [[ "${!name[bc,action2]}" == "doelse" ]]; then
    echo "mission completed"
fi

checked other posts with "eval" but can't get it working.

also tested this and could work but i lost the index name in that way... i need that also.

  all_elems_indirection="${name[@]}"
  echo "works, a list of items :  ${!all_elems_indirection}"
  test3="${name}[$cust,buyer]"
  echo "test3 works : ${!test3}"
  second_elem_indirection="${name}[bc,action2]"
  echo "test 3 works: ${!second_elem_indirection}"

  #but when i want to loop through the indexes from the array with the linked values, it doesn't work, i lost the indexes.
  for i in "${!all_elems_indirection}"; do 
    echo "index name: $i"

  done
3
  • If you can put both the array name into the variable, the variable indirection you used in your second test (${!varname}) should work. See this answer for more details Commented Mar 26, 2022 at 10:02
  • correct @Aaron but than i lost the index, see last updated code i have added in the post. Commented Mar 26, 2022 at 10:07
  • Ah, using the all_elems_indirection you use the special index @ so you can't retrieve the indexes. If you can list all the indexes at some point do that and avoid using @. Otherwise I think you'll want to use a higher-level language (something that has maps) Commented Mar 26, 2022 at 10:31

2 Answers 2

1

With eval, would you please try the following:

#!/bin/bash

declare -A test
test[bc,action2]="doelse"

name="test"

if [[ $(eval echo '$'{"$name"'[bc,action2]}') == "doelse" ]]; then
    echo "mission completed"
fi

As eval allows execution of arbitrary code, we need to pay maximum attention so that the codes, variables, and relevant files are under full control and there is no room of alternation or injection.

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

Comments

1

It's just data. It's just text. Don't restrict yourself to Bash data structures. You can build your abstractions upon any underlying storage.

mydata_init() {
   printf -v "$1" ""
}
mydata_put() {
   printf -v "$1" "%s\n%s\n" "${!1}" "${*:2}"
}
mydata_get2() {
   local IFS
   unset IFS
   while read -r a b v; do
       if [[ "$a" == "$2" && "$b" == "$3" ]]; then
             printf -v "$4" "%s" "$v"
             return 0
       fi
   done <<<"${!1}"
   return 1
}

mydata_init test
mydata_put  test ar action  dosomething
mydata_put  test bc action2 doelse
mydata_put  test bc resolv  dotest
if mydata_get2 test bc action2 var && [[ "$var" == "doelse" ]]; then
   echo "mission completed"
fi

When the built-in features of the language are not enough for you, you can: enhance the language, build your own abstractions, or use another language. Use Perl or Python, in which representing such data structures will be trivial.

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.