Some Metaprogramming (Reflection) In Bash

I needed to write a function in bash that would set an environment variable to that value, unless the variable has been already set. This is a typical metaprogramming (reflection, introspection, etc.) task.

However, searching for the terms I know (reflection, metaprogramming) did not yield any bash results, since the bash terminology is variable variable or dereferencing. I hope the title of this post will help other non-native bash script writers searching for the "wrong" keywords!

The trick is the ${!<variable name>} construct - it will be interpreted as ${<variable name's value>}. An example

$ a="aaaaa"
$ b="bbbbb"
$ echo $a
aaaaa
$ echo $b
bbbbb
$ variable_name="a"
$ echo ${!variable_name}
aaaaa
$ variable_name="b"
$ echo ${!variable_name}
bbbbb

Of course, I could only find it offline (thanks, Dieter!). Armed with this kowledge, the function itself becomes easy -

function env_or_default() {
    name=$1
    default=$2
    if [[ ${!name} == "" ]]; then
        echo "no value set for $name, setting it to default value $default"
        export $name=$default
    else
        echo "value for $name was passed in from the environment, it's value is ${!name}"
    fi
}

Obviously, the echo lines are there just for illustration.

$ env_or_default NOT_SET not-set-default-value
no value set for NOT_SET, setting it to default value not-set-default-value
$ export ALREADY_SET=already-has-value
$ env_or_default ALREADY_SET already-set-default-value
value for ALREADY_SET was passed in from the environment, it's value is already- has-value
$ echo $NOT_SET
not-set-default-value
$ echo $ALREADY_SET
already-has-value

Happy scripting!

P.S.: Krzysztof Wilczynski showed another trick to do this:

random_file_name() {
    local __return=$1
    eval $__return="'$(date +"$(basename -- "$0")_%s_${RANDOM}_$$")'"
}

random_file_name FILE_NAME
echo $FILE_NAME

What do you think? I would love if you would leave a comment - drop me an email at hello@zsoldosp.eu, tell me on Twitter!

Posted on in code, metaprogramming, bash, software by

Share this post if you liked it - on Digg, Facebook, Google+, reddit, or Twitter

Your email address