Search code examples
arrayslinuxbashsamba

Is there in bash an array_combine function, where I can create an associative array from two?


I have two arrays one with user names and other with their full names that are actually dynamically generated by wbinfo -u.

USR=(user1 user2 user3)
FULL=("full user 1" "full user 2" "full user 3")

I want to create an associative array that I can use it with pdbedit so in the loop I would create/modify the user name and full name (in PHP would be easy using array_combine).

pdbedit -u $username -f $fullname

Solution

  • You can implement this yourself using only bash 4.3 built-ins (and no eval) as follows:

    combine() {
      declare key_no key val
      declare -n _keys=$1 _vals=$2 _dest=$3
      declare -g -A "$3"
      for key_no in "${!_keys[@]}"; do
        key=${_keys[$key_no]}
        val=${_vals[$key_no]}
        _dest[$key]=$val
      done
    }
    
    usr=(user1 user2 user3)
    full=("full user 1" "full user 2" "full user 3")
    
    combine usr full arr
    

    This version goes through some extra paranoia to work correctly with sparse arrays.


    If you need to support versions of bash prior to 4.3 (and, ideally, late-series 4.3, as there are security bugs impacting namevar support which could lead to arbitrary code execution in early 4.3 releases), then the following code uses declare to be somewhat more cautious (thanks to Glenn Jackman for suggesting this solution over the prior approach here, which used eval carefully):

    combine() {
      declare keys_var=$1 vals_var=$2 result_var=$3
      declare indirect i keys
      declare -gA "$result_var"
    
      indirect="${keys_var}[@]"; keys=( "${!indirect}" )
      for (( i=0; i < ${#keys[@]}; i++ )); do
        indirect="${vals_var}[$i]"; declare -g "${result_var}[${keys[i]}]=${!indirect}"
      done
    }