4

Why is the output of the following statement true?

VAR="[[ "x"=="y" ]]"
if eval $VAR ; then
    echo "true"
else
    echo "false"
fi

Is there any other way to use a variable as condition for an if statement in bash?

2 Answers 2

7

Your quoting is an issue and you need spaces around ==:

VAR='[[ "x" == "y" ]]'
if eval $VAR ; then
    echo "true"
else
    echo "false"
fi

However you must avoid using eval as far as possible. You can use a function here:

fvar() { [[ "x" == "y" ]]; }

Then call it as:

if fvar; then
    echo "true"
else
   echo "false"
fi

Reasons why your eval condition is evaluating to true because you have VAR="[[ "x"=="y" ]]" where the text inside [[ and ]] is being treated as a single string. Which is same as evaluating [[ a ]] or [[ foo ]]

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

2 Comments

Presumably, the real logic is a bit more complex than "x" == "y" because that can be evaluated to false and thereby simplify a lot of code (it becomes echo "false"). But you're right that eval should be avoided whenever possible.
This would be a better answer kif it answered the question. Why does eval of the string produce success? As you say, there is whitespace missing, but why is the result success? A syntax error would eval as failure... It is fine to tell people what to do, but it is better to explain why; that might save them (or someone else) fr repeating the error.
1

My first answer attempt was voted down, so I'll try to clarify in hopes it at least makes it back to 0 and add something of value considering the other answer. I'll admit I was a bit unclear what you were asking.

First, are your x and y supposed to be literals or variables? Part of the reason I'm uncertain is the extra quoting in the assignment. Note these are equivalent:

$ VAR="[[ "x"=="y" ]]"
$ echo $VAR
[[ x==y ]]
$ VAR="[[ x==y ]]"
$ echo $VAR
[[ x==y ]]

So in this case, saying

if eval $VAR ; then

is the same as saying

if [[ x==y ]]

When you're having trouble with eval, you'll want to print out the value of your variable like this to see what's being executed.

The x==y is one argument, and the [[ operator on a single string argument says, "is this a non-zero length string?" For example:

$ if [[ dkfjek ]]; then echo true; else echo false; fi
true
$ if [[ any_non_zero_length_string ]]; then echo true; else echo false; fi
true
$ if [[ "" ]]; then echo true; else echo false; fi
false

To use the == you need whitespace. For example, without and with eval:

$ if [[ x == x ]]; then echo true; else echo false; fi
true
$ if [[ x == y ]]; then echo true; else echo false; fi
false
$ VAR="[[ x == x ]]"; if eval $VAR; then echo true; else echo false; fi
true
$ VAR="[[ x == y ]]"; if eval $VAR; then echo true; else echo false; fi
false

Usually though you really want to avoid eval unless you've really nailed down what the value of the variable can be. Consider a code snippet where you let the user decide the condition to test: you might write something like this in a script:

read -p "type condition> " COND; 
VAR="[[ $COND ]]"; 
if eval $VAR; 
then 
  echo true; 
else 
  echo false;
fi

You might run it expecting input/output like:

type condition> x == x
true

But what if someone entered this?

type condition> x == x ]]; touch /tmp/oh-no; [[ true
true

What was $VAR? What about /tmp/oh-no?

$ echo $VAR
[[ x == x ]]; touch /tmp/oh-no; [[ true ]]
$ ls -l /tmp/oh-no 
-rw-r--r-- 1 splante isiusers 0 Nov  3 15:17 /tmp/oh-no

Remember the syntax is "if <command>". The "[[" is just one possible command, but any compound command can be executed following if. Now suppose instead of touch /tmp/oh-no the use entered some other more destructive command? It would have executed too.

You asked "Is there any other way to use a variable as condition for an if statement in bash?" This is the typical way to compare two variables for string equivalence in bash:

if [[ "$x" = "$y" ]]; then ...

I assume now you already knew this, but I almost never use eval and just try to work the problem out differently so you don't need to have the whole condition be a variable.

Comments

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.