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 ]]
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With