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 и просто пытаюсь решить проблему по-другому, поэтому вам не нужно, чтобы все условие было переменной.

Другие вопросы по тегам