Я давно пользуюсь Bash, но, похоже, я все еще что-то упускаю. Пожалуйста, рассмотрите этот код:

function surprise {
    true && {
        echo 'Expected';
        false;
    } || {
        echo 'Unexpected';
    }
}

surprise;

сокращенная демонстрация моей реальной проблемы и вывод:

Expected
Unexpected

До сих пор я думал, что то, что возвращает "ожидаемый" блок, не влияет на || перед блоком "Неожиданный", но похоже, что || проверяется не на выводе команды true , а на самом деле команды false внутри скобок.

Может кто-нибудь объяснить, пожалуйста, что на самом деле только что произошло? Заранее спасибо.

3 ответа3

2

Первое: вы можете думать о каждом из "блоков" как о сложных командах, а не как о чем-то существенно отличающемся. Таким образом, то, что у вас действительно есть, это просто:

cmd1 && cmd2 || cmd3

... и тот факт, что cmd2 и cmd3 являются блоками, а не простыми командами, не имеет значения. Теперь важно то, что, учитывая последовательность команд, логический приоритет && и || "операторы" делают это примерно так:

( cmd1 && cmd2 ) || cmd3

(Примечание: на самом деле, эти скобки вызовут подоболочку. Я игнорирую это.) Если вы посмотрите на логическую структуру этого, это ( something ) || cmd3 , ясно, что он будет запускать cmd3 если something не получится Но something на самом деле является cmd1 && cmd2 , что успешно, если * оба cmd1 и cmd2 успешны - что означает, что это терпит неудачу, если терпит неудачу или cmd1 или cmd2 .

Таким образом, логично, что будет заводиться работает cmd3 если либо cmd1 или cmd2 терпит неудачу. В вашем реальном коде cmd2 всегда дает сбой, поэтому cmd3 всегда выполняется.

2

кажется, как || проверяется не на выводе команды true, а на самом деле команды false внутри скобок.

Вы могли бы сказать, что это так.

x && y || z не является структурой if/then/else и не должна использоваться как единица. Он представляет собой комбинацию логических операторов - эквивалент "x AND y OR z" - и оценивает столько команд, сколько ему необходимо для определения результата. (Оценка выполняется слева направо, если она не сгруппирована в скобках или скобках, как в большинстве языков программирования, поэтому порядок (x && y) || z .)

Таким образом, чтобы определить результат x && y , когда x равно true, y также должен быть оценен. С другой стороны, когда x ложно, результат будет ложным, несмотря ни на что, поэтому он просто закоротит и пропустит оценку y.

Являются ли значения между ними одиночными командами или {cmd; cmd; cmd} блоки cmd} вообще не имеют значения; в этой ситуации это просто помогает вам увидеть реальные последствия.

0

Двойной и (&&) и двойной канал (||) имеют значение в управлении процессами в Linux.

Думайте о них как о логических операторах.

command1 && command2

или же

command1 || command2

Или же

command1 && command2 || command3

По сути, во всех 3 случаях command1 выполняется. Если он имеет состояние выхода НЕ НОЛЬ (ошибка какого-либо типа), считается, что он не был успешно запущен.

С && - думая о логическом И в программировании - нет необходимости запускать вторую команду, потому что первая в некотором роде провалилась.

С || - думать о логическом ИЛИ - если первое успешно (выход 0), нет необходимости проверять второе условие - только одно или другое должно быть успешным.

В третьем примере, если command1 выполнена успешно, она запустит command2 . Если это не удалось, вместо этого он запустит command3

В вашем примере, || обнаруживает состояние выхода вашей false команды.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .