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?
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 ]]
"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.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.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.