Чому час [0] переходить у нескінченний цикл?


23

Я бачу таку саму поведінку для циклу нижче, як і цикл з while [ 1 ]. Чому це так?

while [ 0 ]; do
    echo "hello"
done

Відповіді:


33

Одномісні квадратні дужки в оболонці є синонімом test(або окрема команда, або вбудована оболонка), тому [ 0 ]означає те саме, що і test 0. testпризначений для порівняння та тестування атрибутів файлів, про що ви можете прочитати на його сторінці. Коли йому не надано вираз, схожий на порівняння, тест файлів або одну з інших операцій, які він може виконати, він замість цього перевірить, чи є аргумент і не порожній рядок. Ні те, 0ні 1справді є відповідними вхідними даними для тестування, і як тест непустих рядків просто успішно працює, і ваш цикл while цикл назавжди.

Ви можете замість цього спробувати

while false; do
  echo "hello"
done

можливо, замінивши falseна true. А може, ви хочете скористатися (( )):

while (( 0 )); do
  echo "hello"
done

Яка буде вести себе як більшість мов, де 0 означає невдачу / хибність, а 1 означає успіх / істину.


1
Re: "Коли йому не надано вираз, схожий на порівняння, тест файлів або одну з інших операцій, які він може зробити, він просто досягає успіху": Я не думаю, що це хороший спосіб його поставити. Адже [ ](без аргументу) і [ "" ](з єдиним порожнім аргументом) не вдається.
ruakh

3
Як пояснює @ruakh, це твердження є помилковим: коли йому не надано вираз, схожий на порівняння, тест файлів або одну з інших операцій, які він може зробити, він просто успішний. Будь-який єдиний аргумент для тестування (будь-який єдиний аргумент всередині квадратних дужок) вважається ПРАВИЛЬНИМ, якщо аргумент не є порожнім рядком, і обидва, 0і 1не є порожніми рядками. Нові програмісти оболонок часто пишуть if [ 1=2 ]замість if [ 1 = 2 ]і дивуються, чому колишній завжди правдивий. Це правда, тому що це єдиний аргумент і не є порожнім рядком.
Ян Д. Аллен

Хороші бали, я вніс корекцію.
wingedsubmariner

10

Значення 0 тут діє не як числова константа, а як символьний рядок. Ці тести є рівнозначними за своєю дією, що створюють успішний статус припинення:

[ A ]
[ "XYZ" ]
[ 0 ]

вони створюють статус невдалого припинення:

[ ]
[ "" ]

є порожній аргумент, який оцінює логічну правду. Це дозволяє робити такі речі, як:

if [ $UNDER_NUCLEAR_ATTACK ] ; then
  launch-missiles -a $DRY_RUN  # $DRY_RUN set to "-n" during testing
fi

Змінна UNDER_NUCLEAR_ATTACKвстановлюється на будь-яке незаповнене значення, яке вказує на істинне, або не встановлено або порожнє, щоб вказати помилкове.

Ми можемо застосувати !оператора, щоб змінити логіку:

[ ! a ]  # fails: a is nonblank so true; and not true is false.
[ ! ]    # succeeds: blank is false, not blank is true.

Щоб оцінити числовий стан, потрібно використовувати оператори тестування чисел:

 while [ $A -gt $B ] ; do ...

Якщо Aі Bмістять рядки, схожі на десятичні цілі числа, вони порівнюються як числа, а якщо Aбільше, ніж Bцикл. Тож припустимо, що UNDER_NUCLEAR_ATTACKце не буловий чи непустий тип рядка типу, а власне числове булеве значення, яке є 0(помилковим) або іншим значенням (істинним). У такому випадку ми б написали тест так:

 if [ $UNDER_NUCLEAR_ATTACK -ne 0 ] ; then ...

-1

Конструкція if / then перевіряє, чи статус виходу списку команд дорівнює 0 (оскільки 0 означає "успіх" за умовами UNIX), і якщо так, виконує одну чи більше команд.

Словом, ви повертаєте нульовий результат тесту.

http://www.tldp.org/LDP/abs/html/testconstructs.html


5
Так, але не з тієї причини, яку ви, здається, думаєте. Якщо ви [отримуєте лише один аргумент (виключаючи ], звичайно), він виходить зі статусом нуля, якщо аргумент не порожній, ненульовий, якщо він є. Так, наприклад, [ 1 ]також повертається код виходу 0.
Кевін

-1

Значення 0 вважається істинним для циклу while, тому умова для циклу while є істинним, і тому воно неперервне для показу нескінченного циклу. Істинно, якщо ми замінимо 0 на 1, оскільки будь-яке ціле число, яке ми запишемо між умовою, воно поверне істинним

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