Кажется, здесь есть некоторое недопонимание по поводу встроенного в Bash true
, а более конкретно, о том, как Bash расширяет и интерпретирует выражения в скобках.
Код в ответе miku не имеет абсолютно никакого отношения ни к встроенной в Bash true
, ни к /bin/true
, ни к какой-либо другой разновидности команды true
. В этом случае true
является не чем иным, как простой строкой символов, и вызов true
команды / встроенной команды никогда не выполняется ни с помощью присвоения переменной, ни с помощью вычисления условного выражения.
Следующий код функционально идентичен коду в ответе мику:
the_world_is_flat=yeah
if [ "$the_world_is_flat" = yeah ]; then
echo 'Be careful not to fall off!'
fi
Разница только в заключается в том, что сравниваемыми являются четыре символа 'y', 'e', 'a' и 'h' вместо 't', 'r', 'u' и 'е'. Вот и все. Не было предпринято никаких попыток вызвать команду или встроенную команду с именем yeah
, и при этом (в примере miku) не происходит какой-либо специальной обработки, когда Bash анализирует токен true
. Это просто строка, причем совершенно произвольная.
Обновление (2014-02-19): После перехода по ссылке в ответе Мику, теперь я вижу, откуда происходит некоторая путаница. В ответе Мику используются одиночные скобки, но фрагмент кода, на который он ссылается, не использует скобки. Это просто:
the_world_is_flat=true
if $the_world_is_flat; then
echo 'Be careful not to fall off!'
fi
Оба фрагмента кода будут вести себя одинаково, но скобки полностью изменяют то, что происходит под капотом.
Вот что делает Bash в каждом случае:
Без скобок:
- Развернуть переменную
$the_world_is_flat
до строки "true"
.
- Попытка разобрать строку
"true"
как команду.
- Найдите и выполните команду
true
(встроенную или /bin/true
, в зависимости от версии Bash).
- Сравните код выхода команды
true
(который всегда равен 0) с 0. Напомним, что в большинстве оболочек код выхода 0 указывает на успех, а все остальное указывает на сбой.
- Поскольку код выхода был 0 (успех), выполните предложение
then
оператора if
Кронштейны:
- Развернуть переменную
$the_world_is_flat
до строки "true"
.
- Разобрать теперь полностью расширенное условное выражение, имеющее форму
string1 = string2
. Оператор =
является оператором bash сравнения строк . Итак ...
- Выполнить сравнение строк для
"true"
и "true"
.
- Да, две строки были одинаковыми, поэтому значение условного выражения истинно.
- Выполнить предложение
if
оператора then
.
Код без скобок работает, потому что команда true
возвращает код завершения 0, который указывает на успех. Код в скобках работает, потому что значение $the_world_is_flat
идентично строковому литералу true
с правой стороны =
.
Просто чтобы понять, рассмотрим следующие два фрагмента кода:
Этот код (при запуске с правами суперпользователя) перезагрузит компьютер:
var=reboot
if $var; then
echo 'Muahahaha! You are going down!'
fi
Этот код просто печатает "Хорошая попытка". Команда перезагрузки не вызывается.
var=reboot
if [ $var ]; then
echo 'Nice try.'
fi
Обновление (2014-04-14) Чтобы ответить на вопрос в комментариях относительно разницы между =
и ==
: AFAIK, разницы нет. Оператор ==
является синонимом Bash для =
, и, насколько я видел, они работают одинаково во всех контекстах.
Обратите внимание, что я специально говорю об операторах сравнения строк =
и ==
, используемых в тестах [ ]
или [[ ]]
. Я не предполагаю, что =
и ==
взаимозаменяемы везде в bash.
Например, вы явно не можете назначать переменные с помощью ==
, например var=="foo"
(технически вы можете сделать это, но значение var
будет "=foo"
поскольку Bash не видит здесь оператора ==
, он видит оператор =
(присваивание), за которым следует буквальное значение ="foo"
, которое просто становится "=foo"
).
Кроме того, хотя =
и ==
являются взаимозаменяемыми, вы должны помнить, что как эти тесты работают зависит от того, используете ли вы его внутри [ ]
или [[ ]]
, а также о том, цитируются ли операнды. Вы можете прочитать больше об этом в Руководство по расширенному написанию сценариев Bash: 7.3 Другие операторы сравнения (прокрутите вниз до обсуждения =
и ==
).