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.