Home > database >  multi dimensional array (not real) variable name in bash 4.1.2
multi dimensional array (not real) variable name in bash 4.1.2

Time:03-27

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

CodePudding user response:

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.

CodePudding user response:

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.

  •  Tags:  
  • bash
  • Related