0

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.

15
  • I mentioned in my question that I looked at that, and it doesn't fit my criteria. Commented Jan 30, 2019 at 17:05
  • 3
    There is set -u to complain if you use an undefined variable, but it comes with a few caveats. Commented Jan 30, 2019 at 17:08
  • @PMoubed Please share your code because it’s hard to know what you’re trying to do. Do you want to check any Bash file for unset variables? How can you use a variable in a string without having its name? Commented Jan 30, 2019 at 17:17
  • 1
    Why are you using eval? Commented Jan 30, 2019 at 17:30
  • 3
    "I have no control over what would be in the string to be evaluated." This is a recipe for disaster. Invoking eval on unknown content is perhaps the biggest possible error you will ever make. Commented Jan 30, 2019 at 17:31

2 Answers 2

1

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).

Sign up to request clarification or add additional context in comments.

10 Comments

This is very helpfull; what is the purpose of exec 2>&1;?
What happens if you remove it?
also I am getting ${2@Q}: bad substitution, I tried bash and sh.
If I remove exec 2>&1; then err will be empty and error from eval printed out to screen
What OS and bash version? I'm using bash 4 on linux.
|
0

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=""

1 Comment

I was hoping there would be a flag for eval to catch the error. This won't work for me. let's assume all the strings are from a text file.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.