Я бачу таку саму поведінку для циклу нижче, як і цикл з while [ 1 ]
. Чому це так?
while [ 0 ]; do
echo "hello"
done
Я бачу таку саму поведінку для циклу нижче, як і цикл з while [ 1 ]
. Чому це так?
while [ 0 ]; do
echo "hello"
done
Відповіді:
Одномісні квадратні дужки в оболонці є синонімом test
(або окрема команда, або вбудована оболонка), тому [ 0 ]
означає те саме, що і test 0
. test
призначений для порівняння та тестування атрибутів файлів, про що ви можете прочитати на його сторінці. Коли йому не надано вираз, схожий на порівняння, тест файлів або одну з інших операцій, які він може виконати, він замість цього перевірить, чи є аргумент і не порожній рядок. Ні те, 0
ні 1
справді є відповідними вхідними даними для тестування, і як тест непустих рядків просто успішно працює, і ваш цикл while цикл назавжди.
Ви можете замість цього спробувати
while false; do
echo "hello"
done
можливо, замінивши false
на true
. А може, ви хочете скористатися (( ))
:
while (( 0 )); do
echo "hello"
done
Яка буде вести себе як більшість мов, де 0 означає невдачу / хибність, а 1 означає успіх / істину.
0
і 1
не є порожніми рядками. Нові програмісти оболонок часто пишуть if [ 1=2 ]
замість if [ 1 = 2 ]
і дивуються, чому колишній завжди правдивий. Це правда, тому що це єдиний аргумент і не є порожнім рядком.
Значення 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 ...
Конструкція if / then перевіряє, чи статус виходу списку команд дорівнює 0 (оскільки 0 означає "успіх" за умовами UNIX), і якщо так, виконує одну чи більше команд.
Словом, ви повертаєте нульовий результат тесту.
[
отримуєте лише один аргумент (виключаючи ]
, звичайно), він виходить зі статусом нуля, якщо аргумент не порожній, ненульовий, якщо він є. Так, наприклад, [ 1 ]
також повертається код виходу 0
.
Значення 0 вважається істинним для циклу while, тому умова для циклу while є істинним, і тому воно неперервне для показу нескінченного циклу. Істинно, якщо ми замінимо 0 на 1, оскільки будь-яке ціле число, яке ми запишемо між умовою, воно поверне істинним
[ ]
(без аргументу) і[ "" ]
(з єдиним порожнім аргументом) не вдається.