Search code examples
bashvariablesdefined

Bash check if string exists as variable


I need to be able to check if a variety of similar variables are set in bash.

I need to check if the string defined in the variable CONFIG_STRING_TO_CHECK has been set.

I would like to do something like this:

#!/bin/bash

CUSTOM_PREFIX='custom1'

# Common Variable Name Endings:
CONFIG_STRINGS=( "config1" "config2" )

# Loop over common variable endings
for CONFIG_STRING in "${CONFIG_STRINGS[@]}" do :

  # Set the variable name to check
  CONFIG_STRING_TO_CHECK="${CUSTOM_PREFIX}_$CONFIG_STRING"

  # Check if variable is defined
  if [ -z ${CONFIG_STRING_TO_CHECK+x} ]; then
    echo "$CONFIG_STRING_TO_CHECK is declared";
  else
    echo "$CONFIG_STRING_TO_CHECK is not declared"; 
    exit 1;
  fi

done

After some Googling I found this answer, but it doesn't work. I think it's because this is checking if the variable CONFIG_STRING_TO_CHECK is set... which it always is.

Just to be clear, I would like this to check if the following strings are set:

custom1_config1
custom1_config2

Not:

CONFIG_STRING_TO_CHECK

I hope this makes sense. Pease help.


Solution

  • Use indirect expansion (!), as follows:

    ~> A=a
    ~> B=b
    ~> a_b=c
    ~> A_B=${A}_${B}
    ~> echo ${!A_B}
    c
    

    Note that you have to have an intermediate variable name to do this -- you can't do echo ${!${A}_${B}}. see man bash for more details:

    If the first character of parameter is an exclamation point (!), it introduces a level of variable indirection. Bash uses the value of the variable formed from the rest of parameter as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of parameter itself. This is known as indirect expansion. The exceptions to this are the expansions of ${!prefix*} and ${!name[@]} described below. The exclamation point must immediately follow the left brace in order to introduce indirection.


    EDIT: I just tried with this, and it seems to work:

    # !/bin/bash
    
    CUSTOM_PREFIX='custom1'
    
    custom1_config1="hi"
    #custom1_config2="there"
    
    # Common Variable Name Endings:
    CONFIG_STRINGS=( "config1" "config2" )
    
    # Loop over common variable endings
    for CONFIG_STRING in "${CONFIG_STRINGS[@]}"; do
            CONFIG_STRING_TO_CHECK="${CUSTOM_PREFIX}_${CONFIG_STRING}"
            if [ -z ${!CONFIG_STRING_TO_CHECK} ]; then
                    echo ${CONFIG_STRING_TO_CHECK} is not defined
            else
                    echo ${CONFIG_STRING_TO_CHECK} is ${!CONFIG_STRING_TO_CHECK}
            fi
    done
    

    and got:

    ~/tmp/tst3> ./tmp.sh  
    custom1_config1 is hi
    custom1_config2 is not defined