1

I've some associative arrays in a bash script which I need to pass to a function in which I need to access the keys and values as well.

declare -A gkp=( \
   ["arm64"]="ARM-64-bit" \
   ["x86"]="Intel-32-bit" \
)

fv()
{
   local entry="$1"
   echo "keys: ${!gkp[@]}"
   echo "vals: ${gkp[@]}"
   local arr="$2[@]"
   echo -e "\narr entries: ${!arr}"
}

fv $1 gkp

Output for above:

kpi: arm64 x86
kpv: ARM-64-bit Intel-32-bit

arr entries: ARM-64-bit Intel-32-bit

I could get values of array passed to function, but couldn't figure out how to print keys (i.e. "arm64" "x86") in the function.

Please help.

3
  • How do you run this, what value do you give the script? What is $1? Commented Sep 30, 2023 at 11:51
  • @terdon Sry I missed adding invocation info, $1 passed to fv() is dummy for now. But you understood my requirement perfectly. Commented Sep 30, 2023 at 17:05
  • Alternative: pass a string representation of keys & values obtained by @K, unpack it inside into local array. stackoverflow.com/a/75569038/239657 explains how to pass associative array out of function but same techniques work in. Commented May 13 at 14:44

1 Answer 1

1

You need to make the arr variable a nameref. From man bash:

   A  variable  can be assigned the nameref attribute using the -n option
   to the declare or local builtin commands (see the descriptions of  de‐
   clare  and local below) to create a nameref, or a reference to another
   variable.  This allows variables to be manipulated indirectly.   When‐
   ever  the  nameref  variable is referenced, assigned to, unset, or has
   its attributes modified (other than using or changing the nameref  at‐
   tribute  itself),  the operation is actually performed on the variable
   specified by the nameref variable's value.  A nameref is commonly used
   within shell functions to refer to a variable whose name is passed  as
   an  argument  to  the  function.   For instance, if a variable name is
   passed to a shell function as its first argument, running
          declare -n ref=$1
   inside the function creates a nameref variable ref whose value is  the
   variable  name  passed  as the first argument.  References and assign‐
   ments to ref, and changes to its attributes,  are  treated  as  refer‐
   ences,  assignments, and attribute modifications to the variable whose
   name was passed as $1.  If the control variable in a for loop has  the
   nameref attribute, the list of words can be a list of shell variables,
   and a name reference will be established for each word in the list, in
   turn,  when the loop is executed.  Array variables cannot be given the
   nameref attribute.  However, nameref  variables  can  reference  array
   variables  and subscripted array variables.  Namerefs can be unset us‐
   ing the -n option to the unset builtin.  Otherwise, if unset  is  exe‐
   cuted with the name of a nameref variable as an argument, the variable
   referenced by the nameref variable will be unset.

In practice, this would look like:

#!/bin/bash

declare -A gkp=(
   ["arm64"]="ARM-64-bit" 
   ["x86"]="Intel-32-bit" 
)

fv()
{
   local entry="$1"
   echo "keys: ${!gkp[@]}"
   echo "vals: ${gkp[@]}"
   local -n arr_name="$2"
   
   echo -e "\narr entries: ${!arr_name[@]}"
}

fv "$1" gkp

And running it gives:

$ foo.sh foo
keys: x86 arm64
vals: Intel-32-bit ARM-64-bit

arr entries: x86 arm64

Obligatory warning: if you find yourself needing to do something like this in a shell script, it is usually a strong indication that you might want to switch to a proper scripting language like Perl or Python or anything else.

1
  • Exactly what I needed. Thanks! And yes, such logic may be better in Python. Thanks for the advise. I'll have to consider all my env factors to switch properly. Commented Sep 30, 2023 at 17:09

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.