false; echo $?
Вышеуказанное выведет 1
, что противоречит всем другим языкам программирования, которые я знаю.
Любая причина в этом?
false; echo $?
Вышеуказанное выведет 1
, что противоречит всем другим языкам программирования, которые я знаю.
Любая причина в этом?
Это конвенция, но особенно полезная, когда вы думаете об этом. В общем, если программа преуспеет, все, что вам нужно знать. Однако, если это не удается, вам может понадобиться знать все виды информации об ошибке - почему это произошло, как ее исправить и т.д. Имея нулевой средний "успех" и ненулевой средний отказ, вы можете легко проверить успех, и исследуйте конкретную ошибку для получения более подробной информации, если хотите. У многих API и фреймворков есть аналогичные соглашения - функции, которые успешно возвращают 0, а также те, которые не выдают код ошибки, описывающий конкретный случай сбоя.
Bash - это язык программирования (сценариев), а также оболочка и пользовательский интерфейс. Если 0
был ошибкой, то программа могла представить только один вид ошибки.
Однако в Bash любое ненулевое значение является ошибкой, и мы можем использовать любое число от 1-255 для представления ошибки. Это означает, что мы можем иметь много разных видов ошибок. 1
является общей ошибкой, 126
означает, что файл не может быть выполнен, 127
означает "команда не найдена" и т.д. Здесь приведен список кодов выхода Bash со специальными значениями, показывающих некоторые из наиболее распространенных кодов выхода.
Есть также много видов успеха (статус выхода 0
). Тем не менее, успех позволит вам перейти к следующему шагу - вы можете напечатать результаты на экране или выполнить команду и т.д.
Здесь есть две проблемы.
Во-первых, вопрос ОП, почему 0 - это правда, а ложь - это 1 в оболочке? и второе, почему приложения возвращают 0 для успеха и ненулевое значение для сбоя?
Чтобы ответить на вопрос ОП, нам нужно понять второй вопрос. Многочисленные ответы на этот пост описывают, что это соглашение, и перечисляют некоторые тонкости, которые дает это соглашение. Некоторые из этих тонкостей кратко изложены ниже.
Почему приложения возвращают 0 для успеха и не ноль для отказа?
Код, который вызывает операцию, должен знать две вещи о состоянии завершения операции. Операция завершилась успешно? [* 1] А если операция не завершается успешно, почему операция завершается неудачно? Любое значение может быть использовано для обозначения успеха. Но 0 удобнее, чем любое другое число, потому что оно переносимо между платформами. Подводя итог xibo ответ на этот вопрос 16 августа 2011 года:
Ноль не зависит от кодировки.
Если мы хотим сохранить одно (1) в 32-разрядном целочисленном слове, первым вопросом будет "слово с прямым порядком байтов или слово с прямым порядком байтов?", А затем "как долго байты составляют слово с прямым порядком байтов? ", а ноль всегда будет выглядеть одинаково.
Также следует ожидать, что некоторые люди в какой-то момент бросают ошибку на чар или короткую позицию, или даже на плавание. (int) ((char) ENOLCK) не является ENOLCK, если длина char не меньше 8 бит (7-битные ASCII-машины с символами поддерживаются UNIX), тогда как (int) ((char) 0) равен 0 независимо от архитектурные детали чар.
Как только определено, что 0 будет возвращаемым значением для успеха, тогда имеет смысл использовать любое ненулевое значение для отказа. Это позволяет многим кодам выхода ответить на вопрос, почему операция не удалась.
Почему 0 истинно, а ложно 1 в оболочке?
Одним из основных способов использования оболочек является автоматизация процессов с помощью сценариев. Обычно это означает, что вы вызываете операцию, а затем делаете что-то еще в зависимости от состояния выхода из операции. Филипп А. в своем ответе на этот пост прекрасно объяснил, что
В оболочках bash и unix вообще возвращаемые значения не являются логическими. Это целочисленные коды выхода.
Затем необходимо интерпретировать состояние выхода этих операций как логическое значение. Имеет смысл сопоставить успешный (0
) статус выхода с истинным значением, а любой ненулевой статус выхода/состояние отказа - с ложным. Это позволяет условно выполнять связанные команды оболочки.
Вот пример mkdir deleteme && cd $_ && pwd
. Поскольку оболочка интерпретирует 0 как истину, эта команда удобно работает, как и ожидалось. Если бы оболочка интерпретировала 0 как ложное, вам пришлось бы инвертировать интерпретированный статус выхода для каждой операции.
Короче говоря, для оболочки было бы бессмысленным интерпретировать 0 как ложное, учитывая соглашение, что приложения возвращают 0 для успешного завершения.
[* 1]: Да, во многих случаях операции должны возвращать больше, чем просто сообщение об успешном завершении, но это выходит за рамки этого потока.
См. Также Приложение E в Расширенном руководстве по написанию сценариев.
Это просто соглашение о том, что код выхода 0 означает успех. EXIT_SUCCESS будет 0 почти для каждой современной системы.
EDIT:
"почему оба теста 0 и тест 1 возвращает 0 (успех)?"
Это совершенно другой вопрос. Ответ заключается в том, что передача одного аргумента для проверки всегда приводит к успеху, если только этот аргумент не является пустой строкой ( "). См. Документацию Open Group.
Один фундаментальный момент, который я нахожу важным для понимания, - это. В bash и в оболочках unix в общем случае возвращаемые значения не являются логическими. Они являются целыми кодами выхода. Таким образом, вы должны оценить их в соответствии с соглашением, согласно которому 0 означает успех, а другие значения означают некоторую ошибку.
С операторами test
, [ ]
или [[ ]]
условия bash оцениваются как истинные в случае кода выхода 0 (результат/bin/true). В противном случае они будут считаться ложными.
Строки оцениваются иначе, чем коды выхода:
if [ 0 ] ; then echo not null ; fi
if [ $(echo 0) ] ; then echo not null ; fi
if [ -z "" ] ; then echo null ; fi
Арифметический оператор (( ))
интерпретирует 1 и 0 как истинные и ложные. Но этот оператор не может использоваться как полная замена для test
, [ ]
или [[ ]]
. Вот пример, показывающий, когда полезен арифметический оператор:
for (( counter = 0 ; counter < 10 ; counter ++ )) ; do
if (( counter % 2 )) ; then echo "odd number $counter" ; fi
done
Обычно программы возвращают ноль для успеха, отличные от нуля для отказа; false
возвращает 1, потому что это удобное ненулевое значение, но обычно любое ненулевое значение означает отказ какого-либо типа, и многие программы возвращают разные ненулевые значения для указания различных режимов отказа
AFAIK это исходит из соглашения C, что вы должны вернуть 0, если оно выполнено. См:
man close
Большая часть C (POSIX) api построена следующим образом. http://en.wikipedia.org/wiki/C_POSIX_library
Ваша попытка приравнять true/false с успехом/неудачей.
Это две полностью, хотя и тонко, разные дихотомии!
В сценариях оболочки нет такой вещи, как true/false. Обозначения Shell 'не интерпретируются как истинные/ложные. Скорее, "выражения" оболочки - это процессы, которые либо преуспевают, либо терпят неудачу.
Очевидно, что процесс может завершиться неудачей по многим причинам. Таким образом, нам нужны более крупные коды для сопоставления возможных сбоев. Положительные целые числа делают трюк. С другой стороны, если процесс преуспевает, это означает, что он сделал именно то, что он должен был делать. Поскольку есть только один способ сделать это, нам нужен только один код. 0 делает трюк.
В C мы создаем программу. В оболочке script мы запускаем кучу программ, чтобы что-то сделать.
Difference!
это соглашение, датированное ранними днями Unix.
По соглашению, все системные вызовы возвращают 0, если они преуспевают, в противном случае ненулевое значение, потому что тогда разные цифры могут использоваться для указания различной причины сбоя.
Оболочки следуют этому соглашению, 0 означает, что последняя команда выполнена успешно, в противном случае - ноль. Точно так же ненужное возвращаемое значение полезно для выходных сообщений об ошибках: например, 1: "мозг мертв", 2: "бессердечный" и т.д.
Может быть, хороший способ запомнить это: