Compound indirect variable references

Using bash, I'm trying to read a .properties file (name=value pairs), assigning an indirect variable reference for each line in the file.

The trick is that a property's value string may contain the name of a property that occurred earlier in the file, and I want the name of the 1st property to be replaced with the value of that property.

Here's what I have so far:

###############sample.properties:###############
basePath=/home/joe
fullPath=${basePath}/data
###############End sample.properties###############

###############PropertyReader.sh###############
#! /bin/bash
declare -a settings
settings=(`cat sample.properties | tr '\n' ' '`)
for setting in "${settings[@]}"; do
echo
echo "line:"
echo ${setting}

declare -a settingString
settingString=\(\`echo -n $\{setting/=/ \}\`\)
eval "$\{settingString[0]\}="'"$settingString[1]"'

echo "result:"
eval 'echo "$\{settingString[0]\}='"$\{settingString[1]\}"'"'

done
###############End PropertyReader.sh###############

###############output###############

line:
basePath=/home/joe
result:
basePath=/home/joe

line:
fullPath=${basePath}/data
result:
fullPath=basePath[1]/data
###############End output###############

wouldn't it be easier to simply 'source' the file like so:

#! /bin/bash
. sample.properties

echo "fullPath->[${fullPath}]"

If I knew the names of the properties in the file I could do that. But sample.properties is a simplified example. I actually have over 100 properties in the file I need to process, and I'd rather do it in a loop than hard-code all of my property names.

Sourcing the file should work no matter how many properties there are ... can you give us an example with 3 or so properties rather than one?

Hmm... i started work on something similar a while back.

It's a bit shonky as I never really had time to develop it further, but it may help. It won't do the compound variable substitution you outline, but you should be able to implement this using eval.

http://www.zazzybob.com/sh_config.html

You could probably adapt it for your needs to have variable property names instead of hard-codes as i've gone towards here.
i.e. in my script change
eval ${variable}="\"${value}\""
to
echo "${variable} = ${value}"

For the benefit of all, here's the code.... (the sample config file is on the sh_config.html page listed above)

#!/bin/ksh
#< Testing configuration file parsing with ksh
# Can parse out variable = value assignments and then
# uses eval to set shell variables as appropriate - therefore
# you must know which variables are being set so you can reference
# them later. When reading configuration files, you'd normally know
# what needs to be set and what doesn't - and you can check that these
# "pre-known" variables are set and throw errors otherwise....

CONFIG_FILE="./sh_config.conf"
i=0

# Initialise array to lines of file
while read line; do
  initial_array[${i}]="${line}"
  (( i = i + 1 ))
done < ${CONFIG_FILE}

# Set IFS to \n for processing file arrays
oldIFS=${IFS}
IFS='
'

# Comment removal ###########################################
i=0
for line in ${initial_array[@]}; do
   # Test for lines starting with '#'
   echo "${line}" | grep "^#.*$" >/dev/null 2>&1
   if [ "$?" -ne "0" ]; then
      # get rid of any inline comments
      no_comment=`echo "${line}" | sed "s/^\([^#]*\)#.*$/\1/"`
      processed_array[${i}]=${no_comment}    
      (( i = i + 1 ))
   fi
done

# Assignment validation #####################################
for line in ${processed_array[@]}; do
   echo "${line}" | egrep "^[^=]+=[^=]+$" >/dev/null 2>&1
   if [ "$?" -eq "0" ]; then
      # valid syntax
      # remove leading spaces
      first_pass=`echo ${line} |\
          sed "s/^[ 	]*\([^=]*\).*$/\1/"`
      # remove trailing spaces
      second_pass=`echo ${line} |\
          sed -e "s/[ 	]*$//" -e "s/^[^=]*=\([^=]*\)/\1/"`
      # put parts back together
      line="${first_pass}=${second_pass}"
      # remove the assignment operator
      variable=`echo ${line} |\
           sed -e "s/[ 	]*=/=/" -e "s/^\([^=]*\)=[^=]*$/\1/"`
      echo "${variable}" | grep '[[:space:]]' >/dev/null 2>&1
      if [ "$?" -eq "0" ]; then
         echo -en "WARNING: \"${variable}\" contains spaces as " >&2
         echo -en "a variable name - assignment ignored\n" >&2    
         continue
      fi
      value=`echo ${line} |\
          sed -e "s/=[ 	]*/=/" -e "s/^[^=]*=\([^=]*\)/\1/"` 
      export IFS
      eval ${variable}="\"${value}\""
   else
      :
      # invalid syntax
   fi
done

IFS=${oldIFS}

# Now we can cycle through our pre-known variables here checking them
# and acting on them as appropriate.
echo ${backup_dir}
echo ${some_var}

exit 0

EDIT: I wrote this on a Linux box, so you might need to change the echo statements as appropriate (i.e. remove the -en, add \c, etc)

Cheers
ZB

Oh, UUoC by the way

settings=(`cat sample.properties | tr '\n' ' '`)

could be slimmed down to

settings=(`tr '\n' ' ' < sample.properties `)

Cheers
ZB