Ubuntu 22.04.2 LTS
GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)
My Task
I want to test in a generic way if var is set and not empty.
The script
#!/bin/bash
set -e
set -u
set -o pipefail
if [ $# -ne 1 ] ; then
echo "num: $#"
echo "Usage: $0 <VAR_NAME>"
exit 1
fi
varname=$1
cmd="if [ -z "$$varname" ]; then echo "$varname is blank or unset"; else echo "$varname is set to '$$varname'"; fi"
echo "$cmd"
eval "$cmd"
this script a based on that site:
How to check if a variable is set in Bash
The actual behaviour 1 (it does not work)
if you execute your statement like
bla=3
./trv_test_var.sh "bla"
you receive the following response:
if [ -z "$bla}" ]; then echo "bla is blank or unset"; else echo "bla is set to '$bla'"; fi
./trv_test_var.sh: line 19: bla: unbound variable
but if you exceute the outputed command it works as expected:
if [ -z "$bla" ]; then echo "bla is blank or unset"; else echo "bla is set to '$bla'"; fi
bla is set to '3'
The actual behaviour 2 (it works but wrongly)
First of all please change the line 14 with the followin code:
cmd="if [ -z ${$varname+x} ]; then echo "$varname is unset"; else echo "$varname is set to '$$varname'"; fi"
Now:
bla=3
./trv_test_var.sh "bla"
you receive:
if [ -z ${bla+x} ]; then echo "bla is blank or unset"; else echo "bla is set to '$bla'"; fi
bla is blank or unset
but if you exceute the outputed command it works as expected:
if [ -z ${bla+x} ]; then echo "bla is blank or unset"; else echo "bla is set to '$bla'"; fi
bla is set to '3'
The desired behaviour:
I execute the statement with
cmd="if [ -z "$$varname" ]; then echo "$varname is blank or unset"; else echo "$varname is set to '$$varname'"; fi"
and it shows me if the var set or not.
Please help.
2
Answers
This should work :
As said others, try to avoid using
eval
and putting commands in strings.Your approach is difficult.
eval
is not needed and not that easy to make it work.But there is a better and much simpler solution. It relies on the indirection functionality offered by Bash in parameter expansion. The manual says:
Your code can be as simple as:
You can write a function or a script, the code is the same (the body of the function listed above).
Check it online.
Update
It can be done even more simple, without indirection. Use
-v
and do not expand the variable that you want to check. Expand only the parameter to find the name of the variable to check:Check it online.