2016-03-01 2 views
0

Прежде всего, я не профессионал Bash. Несколько месяцев назад я обнаружил, что если я использую как операторы короткого замыкания последовательно с фигурными фигурными скобками, то в случае, если первый оператор выходит с правдивым значением, если последний оператор в истинном блоке выходит из ненулевого, то будет выполнен также блок сбоя. Как это:Понимание короткого замыкания Bash

returnNumber 0 && { 
    echo 'OK' 
    returnNumber 1 
} || { 
    echo 'NG' 
} 

Выведет:

OK 
NG 

Итак, я искал простое решение для этого, и придумал это:

returnNumber 0 && { 
    echo 'OK' 
    returnNumber 1 
    : 
} || { 
    echo 'NG' 
} 

Я знаю, это легко чтобы оставить вне толстой кишки, но является ли это подходящим способом для обхода?

+0

Не делайте вид спорта из использования специального синтаксиса. Когда вы просто пишете 'if-then-else-fi', большинство людей поймут. Попробуйте представить правильные исключения. Я все еще не уверен в своем ответе http://stackoverflow.com/a/28478184/3220113: он эффективен, но его трудно читать. –

ответ

5

Это на самом деле очень распространенный Bash pitfall. Это не ошибка.

returnNumber 0 оценивается как истинный, поэтому второй блок (объединенный логическим и &&) также оценивается, чтобы убедиться, что результат first && second по-прежнему верен.
Второй блок выводит OK, но вычисляет значение false, поэтому теперь результат first && second является ложным. Это означает, что третья часть (объединенная логическим или ||) также должна быть оценена, что также должно отображать NG.


Вместо того, чтобы полагаться на && и ||, вы должны использовать if заявления:

if returnNumber 0; then 
    echo 'OK' 
    returnNumber 1 
else 
    echo 'NG' 
fi 

Т.Л., д-р: Никогда не используйте x && y || z когда y может вернуть статус выхода ненулевого.

0

Г-н Ллама уже прямо ответил на вопрос, это только для краткой справки о том, что происходит для разных «комбинаций». cmd0 - это «команда» с нулевым статусом выхода, а cmd1 - отличным от нуля.

cmd0() { echo -n "[[email protected]]"; return 0; } 
cmd1() { echo -n "[[email protected]]"; return 1; } 
second() { echo "[second]"; } 

doit() { echo "case: [email protected]"; eval "[email protected]"; echo; } 

doit 'cmd0 start && cmd0 first && second' 
doit 'cmd0 start && cmd0 first || second' 
doit 'cmd0 start || cmd0 first && second' 
doit 'cmd0 start || cmd0 first || second' 

doit 'cmd0 start && cmd1 first && second' 
doit 'cmd0 start && cmd1 first || second' 
doit 'cmd0 start || cmd1 first && second' 
doit 'cmd0 start || cmd1 first || second' 

doit 'cmd1 start && cmd0 first && second' 
doit 'cmd1 start && cmd0 first || second' 
doit 'cmd1 start || cmd0 first && second' 
doit 'cmd1 start || cmd0 first || second' 

doit 'cmd1 start && cmd1 first && second' 
doit 'cmd1 start && cmd1 first || second' 
doit 'cmd1 start || cmd1 first && second' 
doit 'cmd1 start || cmd1 first || second' 

производит:

case: cmd0 start && cmd0 first && second 
[start-0][first-0][second] 

case: cmd0 start && cmd0 first || second 
[start-0][first-0] 

case: cmd0 start || cmd0 first && second 
[start-0][second] 

case: cmd0 start || cmd0 first || second 
[start-0] 

case: cmd0 start && cmd1 first && second 
[start-0][first-1] 

case: cmd0 start && cmd1 first || second 
[start-0][first-1][second] 

case: cmd0 start || cmd1 first && second 
[start-0][second] 

case: cmd0 start || cmd1 first || second 
[start-0] 

case: cmd1 start && cmd0 first && second 
[start-1] 

case: cmd1 start && cmd0 first || second 
[start-1][second] 

case: cmd1 start || cmd0 first && second 
[start-1][first-0][second] 

case: cmd1 start || cmd0 first || second 
[start-1][first-0] 

case: cmd1 start && cmd1 first && second 
[start-1] 

case: cmd1 start && cmd1 first || second 
[start-1][second] 

case: cmd1 start || cmd1 first && second 
[start-1][first-1] 

case: cmd1 start || cmd1 first || second 
[start-1][first-1][second] 
Смежные вопросы