pmoubed
pmoubed

Reputation: 3922

How to check if a variable is set in a string in bash?

Let assume I have something like below:

eval link='/var/lib/${XYZ}/test' # string from another text file

XYZ is just for the the example and it could be anything like below:

eval link='/var/lib/${MY_OWN_VAR}/test' # single quote here not double quotes
eval link='/var/lib/${WHAT_EVER}/test'

Is it possible to error out if XYZ is not set? or is there any other way to figure out if XYZ is set or not?

I have looked at this, but the assumption there is that you know the variable name. In my case I have no control over what would be in the string to be evaluated.

UPDATE

To be clear, all the strings that needs to be evaluated are from a text file. basically a program reads a text file and outputs the evaluated strings.

All I am trying here is to figure out a way to gracefully catch "unbound variable" error while evaluating any string. basically what set -u does but gracefully.

Upvotes: 0

Views: 651

Answers (2)

jhnc
jhnc

Reputation: 16797

You can test the eval in a subshell before performing it for real:

assign_if_defined(){
    echo 1>&2 "testing $1=$2"
    outvar="$1"
    input=${2@Q}
    err=$(exec 2>&1; set -u; eval "${outvar}=${input@P}")
    if [ -z "$err" ]; then
        echo 1>&2 "eval test succeeded: doing for real"
        eval "${outvar}=${input@P}"
    else
        echo 1>&2 "eval test failed: not doing for real"
        echo 1>&2 "error: $err"
    fi
}

A=set
assign_if_defined link1 "'"'"\/${A}/'
echo link1=$link1

unset B
assign_if_defined link2 '/$B/'
echo link2=$link2

It seems that the @Q/@P transformations first appeared in bash 4.4. Using them means that quoting is much simplified. If using an older version of bash, you could try normal quoting (eval "${outvar}=\"${input}\"") but the code will fail if input contains special characters (as the first example).

Upvotes: 1

brunorey
brunorey

Reputation: 2255

Well I don't know exactly how much control (or knowledge) you do have on the strings, but can't you just test if it's empty?

VAR=mydirectory
str=/var/lib/${VAR}/test             # valid
str2=/var/lib/${NONEXISTANT}/test    # invalid

if [[ "$str" = "/var/lib//test" ]] ;
then
    echo 'is_empty';
else
    echo 'is_set';
fi;

The only downfall is that the test will fail if you receive a var that is set but empty, e.g. VAR=""

Upvotes: 0

Related Questions