Ответы:
Одиночные квадратные скобки в оболочке являются синонимом test
(либо отдельной команды, либо встроенной оболочки), что [ 0 ]
означает то же самое, что и test 0
. test
предназначен для сравнения и тестирования атрибутов файлов, о чем вы можете прочитать на его man-странице. Если ему не дано выражение, которое выглядит как сравнение, проверка файла или одна из других операций, которые он может выполнить, он вместо этого проверит наличие аргумента и непустую строку. Ни то, 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
(false) или какое-то другое значение (true). В этом случае мы бы написали тест следующим образом:
if [ $UNDER_NUCLEAR_ATTACK -ne 0 ] ; then ...
Конструкция if / then проверяет, равно ли 0 состоянию завершения списка команд (поскольку 0 означает «успех» по соглашению UNIX), и, если это так, выполняет одну или несколько команд.
Короче говоря, вы возвращаете нулевой результат теста.
[
получает только один аргумент (исключая ]
, конечно), он выходит со статусом ноль, если аргумент не пустой, ненулевой, если это так. Так, например, [ 1 ]
также вернет код выхода 0
.
Значение 0 считается истинным для цикла while, поэтому условие для цикла while является истинным и, следовательно, оно непрерывно, чтобы показать бесконечный цикл. Значение true, если мы заменим 0 на 1, так как любое целое число, которое мы записываем между условием, вернет true
[ ]
(без аргумента) и[ "" ]
(с одним пустым аргументом) не удастся.