Я узнаю о структурах принятия решений, и я столкнулся с этими кодами:
if [ -f ./myfile ]
then
cat ./myfile
else
cat /home/user/myfile
fi
[ -f ./myfile ] &&
cat ./myfile ||
cat /home/user/myfile
Они оба ведут себя одинаково. Есть ли какие-то преимущества в использовании одного способа из другого?
shell-script
syntax
control-flow
Субхаа Чандар
источник
источник
Ответы:
Нет, конструкция
if A; then B; else C; fi
иA && B || C
является не эквивалентна .С помощью
if A; then B; else C; fi
командаA
всегда оценивается и выполняется (по крайней мере, делается попытка выполнить ее), а затем оценивается и выполняется либо команда,B
либо командаC
.С
A && B || C
, это же для командA
и ,B
но разные дляC
: командыC
вычисляется и выполняется , если либоA
не удается илиB
не удается.В вашем примере, предположим, что вы
chmod u-r ./myfile
, несмотря на[ -f ./myfile ]
успехи, вы будетеcat /home/user/myfile
Мой совет: используйте
A && B
илиA || B
все, что вы хотите, это остается легко читать и понимать, и ловушки нет. Но если вы имеете в виду, если ... тогда ... еще ... тогда используйтеif A; then B; else C; fi
.источник
Большинству людей легче понять
if
...then
...else
...fi
форму.Для
a && b || c
, вы должны быть уверены, чтоb
возвращает истину. Это является причиной незначительных ошибок и является хорошей причиной, чтобы избежать этого стиля. Если b не возвращает true, это не то же самое.Для очень коротких тестов и действий, у которых нет условия else, укороченная длина является привлекательной, например
&&
и||
этоshort circuiting operators
, как только результат известен дальнейшие ненужные тесты пропускаются.a && b || c
сгруппирован как(a && b) || c
. Первыйa
- это бег. Если онfails
определен как не возвращающий состояние выхода 0, то группа(a && b)
известнаfail
иb
запускать ее не нужно.||
Не знает результат выражения так нужно выполнитьc
. Еслиa
успешно (возвращает ноль), то&&
оператор еще не знает результат,a && b
поэтому должен бежать,b
чтобы узнать. Еслиb
успешно, тоa && b
успешно и||
знает, что общий результат - успех, поэтому запускать не нужноc
. Еслиb
не получится||
все еще не знает значение выражения, поэтому нужно запуститьc
.источник
Оператор && выполняет следующую команду, если предыдущая команда прошла успешно (возвращенный код выхода ($?) 0 = логическое истина).
В форме
A && B || C
команда (или условие) A оценивается, и если A возвращает true (успех, код выхода 0), то команда B выполняется. Если A потерпит неудачу (таким образом, вернет false - код выхода, отличный от 0), и / или B завершится неудачно ( вернет false ), тогда будет выполнена команда C.Также
&&
оператор используется как AND в проверках условий, а оператор||
работает как OR в проверках условий.В зависимости от того, что вы хотите сделать со своим сценарием, форму
A && B || C
можно использовать для проверки условий, как в вашем примере, или можно использовать для цепочки команд и обеспечения выполнения серии команд, если предыдущие команды имели успешный код завершения 0 .Именно поэтому часто можно увидеть такие команды , как:
do_something && do_something_else_that_depended_on_something
.Примеры:
apt-get update && apt-get upgrade
если обновление завершится неудачно, то обновление не будет выполнено (имеет смысл в реальном мире ...).mkdir test && echo "Something" > test/file
Эта часть
echo "Something"
будет выполнена, только если онаmkdir test
прошла успешно и операция вернула код завершения 0 ../configure --prefix=/usr && make && sudo make install
Обычно встречается при компиляции заданий для объединения необходимых зависимых команд.
Если вы попытаетесь реализовать вышеупомянутые «цепочки» с помощью if - then - иначе вам понадобится гораздо больше команд и проверок (и, следовательно, больше кода для написания - больше ошибок) для простой задачи.
Также имейте в виду, что связанные команды с && и || читаются оболочкой слева направо. Вам может потребоваться сгруппировать команды и проверки условий в скобках, чтобы следующий шаг зависел от успешного вывода некоторых предыдущих команд. Например, посмотрите это:
Или пример из реальной жизни:
Имейте в виду, что некоторые команды возвращают разные коды выхода в зависимости от выполняемого процесса или возвращают разные коды в зависимости от их действий (например, команда GNU
diff
возвращает 1, если два файла различаются, и 0, если их нет). К таким командам нужно относиться с осторожностью в && и || ,Также просто, чтобы собрать всю головоломку, помните о конкатенации команд с помощью
;
оператора. В форматеA;B;C
все команды будут выполняться последовательно, независимо от того, какой был код выхода командыA
иB
.источник
Большая часть путаницы по этому поводу может быть связана с документацией bash, вызывающей эти списки AND и OR . Хотя логически похожи на
&&
и||
нашли внутри квадратные скобки, они действуют по- разному.Некоторые примеры могут проиллюстрировать это лучше всего ...
Если
cmda
выход истина,cmdb
выполняется.Если
cmda
выходит false,cmdb
НЕ выполняется, ноcmdc
есть.Как
cmda
выходы игнорируются.Если
cmdb
выход истина,cmdc
выполняется.Если
cmdb
выходит false,cmdc
НЕ выполняется иcmdd
есть.Если
cmda
выход true,cmdb
выполняется, а затемcmdc
.Если
cmda
выходит false,cmdb
НЕ выполняется, ноcmdc
есть.А? Почему
cmdc
выполняется?Потому что для интерпретатора точка с запятой (
;
) и символ новой строки означают одно и то же. Баш видит эту строку кода как ...Чтобы достичь ожидаемого, мы должны заключить
cmdb; cmdc
в фигурные скобки, чтобы сделать их составной командой (групповой командой) . Дополнительная завершающая точка с запятой является лишь требованием{ ...; }
синтаксиса. Итак, мы получаем ...cmda && { cmdb; cmdc; }
Если
cmda
выход true,cmdb
выполняется, а затемcmdc
.Если
cmda
выходит ложная, ниcmdb
илиcmdc
выполняется.Выполнение продолжается со следующей строки.
использование
Условные списки команд наиболее полезны для скорейшего возврата из функций и, таким образом, для избежания интерпретации и выполнения большого количества ненужного кода. Многократные возвраты функций означают, однако, что нужно быть одержимым короткими функциями, чтобы легче было охватить все возможные условия.
Вот пример из бегущего кода ...
источник