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