Get the value of a variable whose name consists of a variable itself

110 views Asked by At

Script:

#!/bin/bash
for SID in db1 db2 db3 db4
do
    "$SID"_fs=$(          
    df -k                           
    | grep "$SID\/data"     
    | tr -s ' '             
    | cut -d' ' -f6         
    | awk  '{print substr($0,length($0),1)}' 
    | sort                          
    | tail -1);
    echo "$SID"_fs
done


./test_sm.sh: line 11: db1_fs=7: command not found
db1_fs
./test_sm.sh: line 11: db2_fs=7: command not found
db2_fs
./test_sm.sh: line 11: db3_fs=3: command not found
db3_fs
./test_sm.sh: line 11: db4_fs=2: command not found
db4_fs

The variables are set to the correct value but the final "echo" does not give me the value of the variable (which is what I require). It instead gives me the variable name.

2

There are 2 answers

1
chepner On BEST ANSWER

Use declare. The following shows both how to set the variable name (using declare) and how to retrieve the value (using indirect parameter expansion).

for SID in db1 db2 db3 db4
do
    name="${SID}_fs"
    value=$(...)
    declare "$name=$value"

    echo "${!name}"
done

bash 4.3 introduces namerefs which simplify this task.

for SID in db1 db2 db3 db4
do
    declare -n sid_fs=${SID}_fs
    sid_fs=$(...)
    echo "$sid_fs"
done

You might consider using an associative array as well, instead of individual parameters.

declare -A fs
for SID in db1 db2 db3 db4; do
    fs[$SID]=$(...)
    echo ${fs[$SID]}
done
2
Oleg Andriyanov On

From http://www.tldp.org/LDP/abs/html/ivr.html:

Indirect referencing in Bash is a multi-step process. First, take the name of a variable: varname. Then, reference it: $varname. Then, reference the reference: $$varname. Then, escape the first $: \$$varname. Finally, force a reevaluation of the expression and assign it: eval newvar=\$$varname.

So in your case:

eval echo \$"$SID"_fs