Eval как будто условие заявления
Почему вывод следующего утверждения верен?
VAR="[[ "x"=="y" ]]"
if eval $VAR ; then
echo "true"
else
echo "false"
fi
Есть ли другой способ использовать переменную как условие для оператора if в bash?
2 ответа
Ваша цитата является проблемой, и вам нужно пространство вокруг ==
:
VAR='[[ "x" == "y" ]]'
if eval $VAR ; then
echo "true"
else
echo "false"
fi
Однако вы должны избегать использования eval
настолько далеко, насколько возможно. Вы можете использовать функцию здесь:
fvar() { [[ "x" == "y" ]]; }
Тогда назовите это как:
if fvar; then
echo "true"
else
echo "false"
fi
Причины, по которым ваш eval
состояние оценивается в true
потому что у вас есть VAR="[[ "x"=="y" ]]"
где текст внутри [[
а также ]]
рассматривается как одна строка. Что так же, как оценка [[ a ]]
или же [[ foo ]]
Моя первая попытка ответа была отклонена, поэтому я попытаюсь уточнить в надежде, что она хотя бы вернется к 0, и добавлю что-то ценное, учитывая другой ответ. Признаюсь, мне было немного неясно, о чем вы спрашивали.
Во-первых, ваши x и y должны быть литералами или переменными? Одна из причин, по которой я не уверен, это дополнительные цитаты в задании. Обратите внимание, что они эквивалентны:
$ VAR="[[ "x"=="y" ]]"
$ echo $VAR
[[ x==y ]]
$ VAR="[[ x==y ]]"
$ echo $VAR
[[ x==y ]]
Так что в этом случае, говоря
if eval $VAR ; then
это то же самое, что сказать
if [[ x==y ]]
Когда у вас возникли проблемы с eval, вы захотите распечатать значение вашей переменной, например, чтобы увидеть, что выполняется.
X ==y - это один аргумент, а оператор [[в единственном строковом аргументе говорит: "это строка ненулевой длины?" Например:
$ 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
Чтобы использовать == вам нужны пробелы. Например, без и с 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
Обычно, хотя вы действительно хотите избежать eval, если вы не знаете, какое значение может иметь переменная. Рассмотрим фрагмент кода, в котором вы позволяете пользователю решать условие для проверки: вы можете написать что-то вроде этого в скрипте:
read -p "type condition> " COND;
VAR="[[ $COND ]]";
if eval $VAR;
then
echo true;
else
echo false;
fi
Вы можете запустить его, ожидая ввода / вывода, например:
type condition> x == x
true
Но что, если кто-то вошел в это?
type condition> x == x ]]; touch /tmp/oh-no; [[ true
true
Что такое $VAR? А как насчет /tmp/ о-нет?
$ 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
Помните, что синтаксис "если <команда>". "[[" - только одна из возможных команд, но любая составная команда может быть выполнена после if. Теперь предположим, что вместо touch /tmp/oh-no
использование вошло в какую-то другую, более разрушительную команду? Это бы тоже исполнилось.
Вы спросили: "Есть ли другой способ использовать переменную в качестве условия для оператора if в bash?" Это типичный способ сравнения двух переменных на эквивалентность строк в bash:
if [[ "$x" = "$y" ]]; then ...
Полагаю, теперь вы уже знали об этом, но я почти никогда не использую eval и просто пытаюсь решить проблему по-другому, поэтому вам не нужно, чтобы все условие было переменной.