Почему в то время как [0] входит в бесконечный цикл?


23

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

while [ 0 ]; do
    echo "hello"
done

Ответы:


33

Одиночные квадратные скобки в оболочке являются синонимом 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 означает успех / истина.


1
Re: «Когда ему не дано выражение, которое выглядит как сравнение, проверка файла или одна из других операций, которые он может выполнить, это просто успешно»: я не думаю, что это хороший способ выразить это. В конце концов, [ ](без аргумента) и [ "" ](с одним пустым аргументом) не удастся.
Руах

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(false) или какое-то другое значение (true). В этом случае мы бы написали тест следующим образом:

 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 является истинным и, следовательно, оно непрерывно, чтобы показать бесконечный цикл. Значение true, если мы заменим 0 на 1, так как любое целое число, которое мы записываем между условием, вернет true

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.