Во время работы над цепочкой инструментов проекта стало очевидно, что я не понимаю bash
списков.
Из руководства:
"руководство": man bash
Списки:
Список — это последовательность из одного или нескольких конвейеров, разделенных одним из операторов ;, &, && или ||,
[...]
Из этих операторов списка && и || имеют равный приоритет, за которым следует ; и &, которые имеют одинаковый приоритет.
[...]
Списки И и ИЛИ — это последовательности одного или нескольких конвейеров, разделенные знаками && и || операторы управления соответственно. Списки И и ИЛИ выполняются с левой ассоциативностью. Список AND имеет форму
команда1 && команда2
команда2 выполняется тогда и только тогда, когда команда1 возвращает нулевой статус выхода.
Список ИЛИ имеет вид
команда1 || команда2
команда2 выполняется тогда и только тогда, когда команда1 возвращает ненулевой статус выхода. Статус возврата списков И и ИЛИ — это статус выхода последней команды, выполненной в списке.
[Форматирование]
Вместо кода, который выглядит так:
command1
if [ $? -eq 0 ];
then
command2
fi;
Мы можем просто сделать это:
command1 && command2
В одном из имеющихся у меня скриптов есть код, функционально эквивалентный этому:
#!/bin/bash
s () { return 0; }
f () { return 1; }
l () { echo "Y"; }
#Why does this output "Y"?
f && f || true && s && l
#This does what I want:
f && { f; s && l; }
В приведенном выше примере я ожидаю (и очень хочу), чтобы f || true && s && l
выполнялся только в том случае, если f
не выйдет из строя. Но, увы, я должен использовать f && { f; s && l; }
, чтобы получить желаемую функциональность.
Что я неправильно понимаю? Почему цепочка «продолжает идти» после первого &&
?
Разве цепочка команд не должна прекращать выполнение после f &&
, потому что "команда2 выполняется тогда и только тогда, когда команда1 возвращает ненулевой статус выхода"?
PS: я ожидаю, что это будет работать так.
if (f == 0) {
if (f != 0) {
if (0 == 0) {
if (s == 0) {
l;
}
}
}
}
f && f || true && s && l
анализируется как(((f && f) || true) && s) && l
(недействительный синтаксис оболочки, круглые скобки используются только для демонстрации).... || true
всегда верно, поэтомуs
выполняется всегда. - person melpomene   schedule 03.12.2016if
.) - person J. Allan   schedule 03.12.2016&&
или цепочки||
, лучше всего использовать явный операторif
. Смешивание двух никогда не будет более четким и часто будет более подвержено ошибкам. - person chepner   schedule 03.12.2016if f; then f; s && l; fi
(которое в скрипте не будет помещено в одну строку, а будет правильно разделено и с отступом). - person chepner   schedule 03.12.2016if f; ...
, так что спасибо, что указали на это. Раньше я бы сделалf; if [ $? -eq 0 ]; ...
.) - person J. Allan   schedule 03.12.2016