Эти &&
и ||
операторы не точные встроенные замены для если-то-иначе. Хотя, если их использовать осторожно, они могут сделать почти то же самое.
Один тест прост и однозначен ...
[[ A == A ]] && echo TRUE # TRUE
[[ A == B ]] && echo TRUE #
[[ A == A ]] || echo FALSE #
[[ A == B ]] || echo FALSE # FALSE
Однако попытка добавить несколько тестов может привести к неожиданным результатам ...
[[ A == A ]] && echo TRUE || echo FALSE # TRUE (as expected)
[[ A == B ]] && echo TRUE || echo FALSE # FALSE (as expected)
[[ A == A ]] || echo FALSE && echo TRUE # TRUE (as expected)
[[ A == B ]] || echo FALSE && echo TRUE # FALSE TRUE (huh?)
Почему отражаются как ЛОЖЬ, так и ИСТИНА?
Здесь происходит то, что мы не осознали этого &&
и ||
являемся перегруженными операторами, которые действуют внутри скобок условных тестов иначе, [[ ]]
чем в списках AND и OR (условное выполнение), которые мы здесь имеем.
Из справочной страницы bash (отредактировано) ...
Списки
Список - это последовательность из одного или нескольких конвейеров, разделенных одним из операторов;, &, && или ││ и, возможно, завершенных одним из;, &, или. Из этих операторов списка && и ││ имеют одинаковый приоритет, после чего следует; и &, которые имеют равный приоритет.
Последовательность из одного или нескольких символов новой строки может появиться в списке вместо точки с запятой для разделения команд.
Если команда завершается оператором управления &, оболочка выполняет команду в фоновом режиме в подоболочке. Оболочка не ожидает завершения команды, и возвращается статус 0. Команды, разделенные символом a; выполняются последовательно; оболочка ожидает завершения каждой команды по очереди. Статус возврата - это статус выхода последней выполненной команды.
Списки AND и OR являются последовательностями одного из нескольких конвейеров, разделенных управляющими операторами && и, соответственно. Списки AND и OR выполняются с левой ассоциативностью.
Список AND имеет вид ...
command1 && command2
Command2 выполняется тогда и только тогда, когда command1 возвращает нулевое состояние выхода.
Список ИЛИ имеет форму ...
command1 ││ command2
Command2 выполняется тогда и только тогда, когда command1 возвращает ненулевой статус выхода.
Статус возврата списков AND и OR - это статус выхода последней команды, выполненной в списке.
Возвращаясь к нашему последнему примеру ...
[[ A == B ]] || echo FALSE && echo TRUE
[[ A == B ]] is false
|| Does NOT mean OR! It means...
'execute next command if last command return code(rc) was false'
echo FALSE The 'echo' command rc is always true
(i.e. it successfully echoed the word "FALSE")
&& Execute next command if last command rc was true
echo TRUE Since the 'echo FALSE' rc was true, then echo "TRUE"
Хорошо. Если это правильно, то почему следующий к последнему примеру что-нибудь эхо?
[[ A == A ]] || echo FALSE && echo TRUE
[[ A == A ]] is true
|| execute next command if last command rc was false.
echo FALSE Since last rc was true, shouldn't it have stopped before this?
Nope. Instead, it skips the 'echo FALSE', does not even try to
execute it, and continues looking for a `&&` clause.
&& ... which it finds here
echo TRUE ... so, since `[[ A == A ]]` is true, then it echos "TRUE"
Риск логических ошибок при использовании более одной &&
или ||
в списке команд довольно высок.
рекомендации
Один &&
или ||
в списке команд работает, как ожидалось, так что это довольно безопасно. Если это ситуация, когда вам не нужно выражение else, может быть понятнее что-то вроде следующего (фигурные скобки необходимы для группировки последних 2 команд) ...
[[ $1 == --help ]] && { echo "$HELP"; exit; }
Множественные операторы &&
и ||
операторы, где каждая команда, кроме последней, является тестом (т. Е. Внутри скобок [[ ]]
), обычно также безопасны, поскольку все, кроме последнего оператора, ведут себя так, как ожидается. Последний оператор действует больше как предложение then
или else
.
&&
и||
операторы оболочки , как и вcmd1 && cmd2 || cmd3
имеют одинаковый приоритет, то&&
по прибытии((...))
и[[...]]
имеет приоритет над||
(((a || b && c))
есть((a || (b && c)))
). То же самое касается-a
/-o
вtest
/[
иfind
и&
/|
вexpr
.