2

I am building a provisioning script that fills in variables, from where they are centrally defined in a bash file, into various non-bash files (sql, nginx, etc.) as a part of spinning up a VM.

What I need is to build an associative array thats populated with my local variables.

For example:

#!/usr/bin/env bash
var1=abc
var2=123
var3=xyz
declare -A vars_list

#magic script would produce this:
vars_list=([var1]=$var1 [var2]=$var2 [var3]=$var3)

#print out
for i in "${!vars_list[@]}"
do
  echo "key  : $i"
  echo "value: ${vars_list[$i]}"
done

will yield:

key : var1
value: abc
key : var3
value: xyz
key : var2
value: 123

Been trying this for way too long. Seems like this is another thing that bash just cannot do simply. Help?

Alexi Theodore
  • 1,177
  • 10
  • 16
  • Did you see this [SO question](https://stackoverflow.com/questions/1494178/how-to-define-hash-tables-in-bash)? What version of bash (`bash --version`)? – jeremysprofile May 20 '18 at 17:28
  • Why do you need it? Where are the variable names coming from? – choroba May 20 '18 at 18:31
  • 1
    @jeremysprofile are you referencing associative arrays? The primary issue here is pulling out all the local variables dynamically, not manually. Not sure if thats what you were referencing. Bash version is 4.2 – Alexi Theodore May 20 '18 at 21:04
  • @choroba, I need it because I am trying to set all the variables in a build script in one place. The build script (bash) takes those env variables and puts them into sql build files, nginx files and potentially other domains as well - ones that don't have a direct interface in bash. I could technically embed it all in bash, but it would be very messy and I just don't do that. – Alexi Theodore May 20 '18 at 21:08
  • Is there a reason you don't run `set -a` ahead-of-time to export those variables to the environment when they're created? That would enable some simpler techniques (such as `while IFS== read -r -d '' key val; do array[$key]=$val; done < <(cat /proc/self/environ)`). – Charles Duffy May 20 '18 at 23:08

3 Answers3

0

You can try this way.

var1=abc
var2=123
var3=xyz
declare -A vars_list

#magic script would produce this:
vars_index=('var1' 'var2' 'var3')
for ((i=0;i<${#vars_index[@]};i++))
do
    vars_list["${vars_index[i]}"]="${!vars_index[i]}"
done

#print out
for i in "${!vars_list[@]}"
do
    echo "key  : $i"
    echo "value : ${vars_list[$i]}"
done
ctac_
  • 2,413
  • 2
  • 7
  • 17
  • Thanks, thats definitely half of it. However the hard part is getting the list of local variables dynamically (in other words, without the assistance of the vars_index). I've tried several different methods, including "declare", "printenv", "set" and "env", but none of them seem to have a clean avenue to getting what I need. – Alexi Theodore May 20 '18 at 20:19
0

How is

var1=abc
var2=123
var3=xyz

better than

declare -A vars_list
vars_list=(
    [var1]=abc
    [var2]=123
    [var3]=xyz
)

? Just assign to the associative array directly.

choroba
  • 231,213
  • 25
  • 204
  • 289
0
declare -A vars
while IFS= read -r var; do
  vars[$var]=${!var}
done < <(compgen -v)

compgen -v lists currently-defined variables (names only, no values, avoiding the parsing difficulties present with set and uncontrolled values).

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • This looks promising, but I cannot get it to run without error. I'm not familiar with the "< <(... )" syntax on the done line to troubleshoot it. – Alexi Theodore May 21 '18 at 00:44