Я бачу таку саму поведінку для циклу нижче, як і цикл з 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, оскільки будь-яке ціле число, яке ми запишемо між умовою, воно поверне істинним
[ ](без аргументу) і[ "" ](з єдиним порожнім аргументом) не вдається.