1

What I have is an array with some variables. I can iterate to get the values of those vars but what I need is actually their names (values will be used elsewhere).

Going with var[i] won't work cause I will have different names. I guess I could workaround this by creating another array with the names - something similar to this: Getting variable values from variable names listed in array in Bash

But I'm wondering if there is a better way to do this.

var1=$'1'
var2=$'2'
var3=$'3'

Array=( $var1 $var2 $var3)

for ((i=0; i<${#Array[@]}; i++))
do
  echo ${Array[i]}
done

Is:

>1
>2
>3

Should be:

>var1
>var2
>var3
4
  • 2
    Why don't you just store the strings var1 var2 var3 in your array? Commented May 11, 2018 at 14:58
  • 2
    var1=1; var2=2; var3=3; Array=( $var2 $var2 $var3 ) results in Array=( 1 2 3 ). The entries aren't linked to variables in any significant way -- if you then afterwards ran var1=4; var2=5; var3=6, the array would still be 1 2 3; as such, there isn't any metadata to retrieve. Commented May 11, 2018 at 15:01
  • (and $'1' is exactly the same as 1; there's no point whatsoever to using the alternate literal syntax here -- in most of the cases where there was a point to using that syntax, you'd need to make it Array=( "$var1" "$var2" "$var3" ) to avoid munging your data during the assignment). Commented May 11, 2018 at 15:02
  • BTW, a language that did allow what you're asking for would be exceedingly rare. In Python, for example, if you set var1=1; var2=2; var3=3; Array=[ var1, var2, var3 ], you can't get back from Array[0]'s value of 1 to the variable var1 it was originally taken from (especially since var1 may no longer have the value 1 at the future point in time when the inspection is desired). Commented May 11, 2018 at 15:26

2 Answers 2

4

It sounds like you want an associative array.

# to set values over time
declare -A Array=( ) || { echo "ERROR: Need bash 4.0 or newer" >&2; exit 1; }
Array[var1]=1
Array[var2]=2
Array[var3]=3

This can also be assigned at once:

# or as just one assignment
declare -A Array=( [var1]=1 [var2]=2 [var3]=3 )

Either way, one can iterate over the keys with "${!Array[@]}", and retrieve the value for a key with ${Array[key]}:

for var in "${!Array[@]}"; do
  val="${Array[$var]}"
  echo "$var -> $val"
done

...will, after either of the assignments up top, properly emit:

var1 -> 1
var2 -> 2
var3 -> 3
Sign up to request clarification or add additional context in comments.

Comments

1

What about this solution?

#!/bin/bash

var1=$'1'
var2=$'2'
var3=$'3'

Array=( var1 var2 var3 )

for var in "${Array[@]}"; do
  echo "$var = ${!var}"
done

The idea just consists in putting your variable names in the array, then relying on the indirection feature of Bash.

But as pointed out by @CharlesDuffy, the use of associative arrays sounds better adapted to the OP's use case.

Also, this related article may be worth reading: How can I use variable variables… or associative arrays?

1 Comment

The OP's question links to stackoverflow.com/questions/29307073/… showing exactly this technique, so I believe they're already familiar with it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.