Чому 0 відповідає дійсності, але неправда - 1 в оболонці?


122
false; echo $?

Викладене вище буде результатом 1, що суперечить усім іншим мовам програмування, які я знаю.

Будь-яка причина в цьому?


3
Це також відповідає Унікс Шляху ... не повертайте нічого успіху.
Абдулла Джибалі

21
Тому що статус виходу не є булевим. Просто як це.
Єнс

2
Майте на увазі, що falseце не є булевим, як у інших мовах програмування. Це просто програма, розміщена за адресою /bin/false( /usr/bin/falseна Mac), яка завжди повинна повертати код виходу з помилки 1. Подібно до true. Тож тут немає такого поняття, як кастинг. Це просто все про вихідні коди.
Михайло Васін

Оболонка - це (користувальницький) інтерфейс до операційної системи. Програми Unix і т.д. відповідають умові виходу з 0 як "ОК" з причини, вказаної у відповідях (можливість передавати більше однієї причини відмови). Оболонка просто зберігає цю умову, що робить конструкції на зразок if myprog; then echo OK; fiлегкими та інтуїтивними. Інакше вам доведеться перевернути кожен тест на успіх програми!
Пітер - Відновіть Моніку

Відповіді:


93

Це умова, але особливо корисна, коли ви думаєте про це. Загалом, якщо програма успішна, це все, що потрібно знати. Якщо це не вдалося, однак, можливо, вам доведеться знати всіляку інформацію про збій - чому це сталося, як виправити і т.д. , і вивчіть конкретну помилку, щоб отримати докладнішу інформацію. Багато API та фреймворків мають схожу умову - функції, які успішно повертають 0, і ті, які не вдається, повертають код помилки, що описує конкретний випадок відмови.


6
Я розумію цю відповідь, але я все ще не розумію, чому перевернуто перетворення від bool до int. Чи є "повернення булевої конвенції", яке говорить: якщо ви повертаєте true, це означає, що помилок немає, якщо ви повертаєте false, це означає помилку (як "ціле = конвенція про помилку коду", яка більш відома)?
Guillaume86

1
Якщо припустити, що існує булеве перетворення int, то це означає, що ви насправді не зрозуміли відповідь. Нуль означає успіх, і всі 1, 2, ..., 255 - це коди помилок, які можуть корисно передавати різні сценарії відмов. Конкретний приклад - xargsце використання різних кодів помилок у діапазоні близько 127, щоб вказати на те, як група команд вийшла з ладу. Перетворення, яке може бути здійснено, - int to bool, де 0 відображається на успіх (що, мабуть, ви хочете виразити як істинне / 1; але розумієте, що це лише інша умовна умова) та всі інші значення до відмови.
тріплей

79

Bash - мова програмування (сценаріїв), але це також оболонка та користувальницький інтерфейс. Якщо 0була помилка, то програма могла представити лише один вид помилок.

Однак у Bash будь-яке ненульове значення є помилкою, і ми можемо використовувати будь-яке число від 1-255, щоб представити помилку. Це означає, що ми можемо мати багато різних помилок. 1є загальною помилкою, 126означає, що файл не може бути виконаний, 127означає "команда не знайдена" і т. д. Ось список вихідних кодів Bash зі спеціальними значеннями, що показують деякі найпоширеніші коди виходу.

Також є багато видів успіху (статус виходу є 0). Однак успіх дозволить вам перейти до наступного кроку - ви можете сподобати результати друку на екрані, або виконати команду тощо.


8
Ця прагматична відповідь, що показує корисність різноманітних зворотних кодів, є кращою перед проповідністю деяких інших відповідей.
javadba

1
І лише заради цього, я зазначу, що /usr/include/sysexits.hнотатки значень виходу, які, можливо, є більш прагнутими, навіть якщо конвенція, яку вони представляють, сягає 1980-х років. Ця конвенція існує поза сферою баш.
ghoti

2
Чудове, просте і прагматичне пояснення. Це має бути вгорі.
Рей Леонард Аморато

3
"Якщо 0була помилка, то програма могла представити лише один вид помилки" . Ця заява є ключовою і причиною, за якою ця відповідь має бути вгорі.
rayryeng

1
@LuisLavaire Це невизначена поведінка. На практиці кількість має тенденцію до скорочення; але, безумовно, не буде "більш помилково", якби час виконання породжував попередження та / або просто виходив з ладу. ОС зарезервувала рівно один байт для цієї інформації, і намагаючись поставити більше одного байта, безумовно, є помилка. Але дизайнери ОС, мабуть, в перший день зіткнулися з аваріями і знизали плечима, і вирішили, що найкраще, що вони можуть зробити, - це просто скоротити значення і рухатися далі.
трійчатка

30

Тут є два суміжні питання.

По-перше, питання ОП: Чому 0 відповідає дійсності, але неправда - 1 в оболонці? по-друге, чому додатки повертають 0 за успіх, а не нуль - для відмови?

Щоб відповісти на питання ОП, нам потрібно зрозуміти друге питання. Численні відповіді на цю публікацію описали, що це конвенція, і перерахували деякі приємності, які ця конвенція надає. Деякі з цих смаків наведені нижче.

Чому програми повертають 0 за успіх, а нульове - за помилку?

Код, який викликає операцію, повинен знати дві речі про стан виходу з операції. Чи завершилася операція успішно? [* 1] І якщо операція не закінчується успішно, чому операція завершилася невдало? Будь-яке значення може бути використане для позначення успіху. Але 0 зручніше, ніж будь-яке інше число, оскільки воно переноситься між платформами. Підсумовуючи відповідь xibo на це запитання 16 серпня 2011 року:

Нуль не кодує.

Якби ми хотіли зберегти одне (1) у 32-бітному цілому слові, першим питанням було б «слово великого ендіану чи мало-ендіанське слово?», А далі «як довго байти складають слово мало-ендіанців? ", а нуль завжди буде виглядати однаково.

Крім того, слід очікувати, що деякі люди кидають errno на char або короткий в якийсь момент, або навіть плавати. (int) ((char) ENOLCK) не є ENOLCK, коли char не менше 8-бітової довжини (7-бітні машини ASCII char підтримуються UNIX), тоді як (int) ((char) 0) 0 не залежить від архітектурні деталі char.

Як тільки буде визначено, що 0 буде повернутим значенням для успіху, тоді має сенс використовувати будь-яке ненульове значення для відмови. Це дозволяє багатьом вихідним кодам відповісти на питання, чому операція не вдалася.

Чому 0 відповідає дійсності, але неправда - 1 в оболонці?

Одне з основних принципів використання снарядів - автоматизація процесів шляхом їх написання. Зазвичай це означає викликати операцію, а потім робити щось інше, умовно на основі статусу виходу з операції. Філіп А. чудово пояснив у своїй відповіді на цю посаду, що

У bash і в оболонках Unix взагалі значення повернення не булеві. Вони є цілими кодами виходу.

Тоді необхідно інтерпретувати статус виходу цих операцій як булеве значення. Має сенс зіставити успішний ( 0) статус виходу на істинний, а будь-який ненульовий / вихідний вихідний - на помилковий. Це дозволяє умовно виконувати ланцюгові команди оболонки.

Ось приклад mkdir deleteme && cd $_ && pwd. Оскільки оболонка інтерпретує 0 як справжню, ця команда зручно працює, як очікувалося. Якщо оболонка повинна інтерпретувати 0 як помилкову, вам доведеться інвертувати інтерпретований статус виходу для кожної операції.

Коротше кажучи, було б безглуздо для оболонки інтерпретувати 0 як хибну, враховуючи умову, що програми повертають 0 за успішний статус виходу.


[* 1]: Так, багато разів операції потребують повернення більше, ніж просто повідомлення про успіх, але це виходить за межі цього потоку.

Дивіться також Додаток E у Додатковому посібнику з написання сценарію


2
Привіт, просто наголошую, що якби оболонка інтерпретувала нуль як хибний, а ненульовий як істинний, хитрість робити mkdir deleteme && cd _$ && pwdнасправді не провалилася б; але нам доведеться замінити це на mkdir deleteme || cd _$ || pwd, що, на мою думку, є набагато менш зрозумілим, адже те, що ми насправді хочемо зробити, це mkdir deleteme" і " cd _$" і " pwd... (причому "і" мають тут своє значення від звичайної мови).
Ремі Пейре

1
Я думаю, що я висвітлив це у своїй відповіді. Щоб було зрозуміло, якщо ви інвертуєте логіку, недостатньо просто замінити &&операторів ||операторами. Вам потрібно буде повністю застосувати закон Де Моргана. Дивіться: en.wikipedia.org/wiki/De_Morgan%27s_laws
axiopisty

1
Інший розгляд: я бачу щонайменше три причини, чому в загальних рисах було б природно заявити, що trueвідповідає нулю і falseвідповідає нулю. По-перше, якщо я вам щось скажу, "кажу вам правду" залежить від кількості брехні, яку я сказав: або це нуль, і я сказала (в усьому світі) правду, або це ненулеве значення, і я збрехав. Це, по суті, те, що потрібно, щоб логічне andвідповідало загальним додаванням "і" (очевидно, якщо обмежуватись натуральними числами).
Ремі Пейре

1
(продовження з попереднього коментаря). Друга причина полягає в тому, що є одна правда, але багато неправди; Отже, зручніше пов'язувати єдине значення для trueта всі інші значення для false. (Це по суті те саме, що і міркування щодо повернених значень програм).
Ремі Пейре

(продовження з попереднього коментаря). Третя причина полягає в тому, що «правда, що правда, що А» є те саме, що «правда, що А», «помилково, що неправда, що А» є те саме, що «помилково, що А», і т.д .; так що він trueведе себе як мультиплікативний 1 і falseяк мультиплікативний -1. Що, як сили -1, означає, що trueповодиться додатково як "парне" і false"непарне". Знову ж таки, це trueзаслуговує на нуль ...
Ремі Пейре

17

Єдиний фундаментальний момент, який я вважаю важливим для розуміння, це такий. У 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

Дякуємо за пояснення дужок проти дужок на true / false
javadba

15

Це лише умова, що 0 вихідний код означає успіх. EXIT_SUCCESS буде 0 на майже кожній сучасній системі.

Редагувати:

"чому і тест 0, і тест 1 повертає 0 (успіх)?"

Це зовсім інше питання. Відповідь полягає в тому, що передача одного аргументу для тестування завжди приносить успіх, якщо цей аргумент не є нульовим рядком (""). Дивіться документацію щодо відкритої групи .


Тоді чому і те, test 0і test 1повертає 0 (успіх)?
httpinterpret

5
@httpinterpret, testне перевіряє числових значень. Він перевіряє, чи є цей рядок нульовим рядком. man testдля отримання додаткової інформації.
Карл Норум

12

Зазвичай програми повертають нуль для успіху, не нульовий за збій; falseповертає 1, оскільки це зручне ненульове значення, але, як правило, будь-яке ненульове значення означає якийсь збій, і багато програм повертають різні ненульові значення для вказівки різних режимів відмови


2
Громадяни без пояснень (або очевидних причин) того, що смокчуть, а ті, хто це робить, кульгають, бо зовсім не допомагають громаді.
Абдулла Джибалі

1
Чи не потурання це ... але це їх 2 очка ... і @MichaelMrozek .. з 19.6k, він не може пошкодити занадто погано, лол.
Алекс Сірий

1
@alexgray Це було два роки тому; на той час у мене було близько 5 к. І мені було цікавіше, що було не так у відповіді, ніж про представника
Майкл Мрозек


4

це конвенція, що датується першими днями Unix.

За умовами, всі системні виклики повертають 0, якщо це вдалося, не нульове в іншому випадку, оскільки тоді різні цифри можуть використовуватися для вказівки різної причини відмови.

Оболонки дотримуються цієї конвенції, 0 означає, що остання команда вдалася, інакше не нульова. Аналогічно, ненульове значення повернення корисне для вихідних повідомлень про помилки: наприклад, 1: "мозг мертвий", 2: "безсердечно" тощо.



3

Ваша спроба прирівняти справжнє / хибне до успіху / невдачі.

Вони дві повністю, хоча спочатку тонко, різні дихотомії!

У сценаріях оболонок немає такого поняття, як правда / хибність. "Виразки" оболонок не трактуються як істинні / хибні. Швидше, «вирази оболонки» - це процеси, які успішно або не вдається.

Очевидно, що процес може вийти з ладу з багатьох причин. Таким чином, нам потрібен більший набір кодів для відображення можливих відмов. Позитивні цілі чини. З іншого боку, якщо процес вдався, це означає, що він зробив саме те, що повинен був зробити. Оскільки існує лише один спосіб зробити це, нам потрібен лише один код. 0 робить трюк.

В C ми створюємо програму. У сценарії оболонки ми запускаємо купу програм, щоб щось зробити.

Різниця!


Це заплутано. Введіть 'man ['. Це показує Тестова утиліта оцінює вираз і, якщо вона оцінюється як істина, повертає нульовий (справжній) статус виходу; в іншому випадку він повертає 1 (false). Якщо виразу немає, тест також повертає 1 (false).
кавалькад

1

Можливо, гарний спосіб запам'ятати це:

  • Зворотні коди відповідають "що відповідь?" справжній (або інший результат) або хибний
  • Вихідні коди відповідають "у чому проблема?" вихідний код або немає проблеми (0)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.