Widzę to samo zachowanie dla pętli poniżej, jak dla pętli while [ 1 ]
. Dlaczego to jest takie?
while [ 0 ]; do
echo "hello"
done
Widzę to samo zachowanie dla pętli poniżej, jak dla pętli while [ 1 ]
. Dlaczego to jest takie?
while [ 0 ]; do
echo "hello"
done
Odpowiedzi:
Pojedyncze nawiasy kwadratowe w powłoce są synonimem test
(osobnego polecenia lub wbudowanej powłoki), więc [ 0 ]
oznaczają to samo co test 0
. test
służy do przeprowadzania porównań i testowania atrybutów plików, o czym można przeczytać na stronie podręcznika. Jeśli nie zostanie podane wyrażenie, które wygląda jak porównanie, test pliku lub jedna z innych operacji, które może wykonać, zamiast tego przetestuje, czy argument jest obecny i niepusty ciąg znaków. Nie są 0
ani nie 1
są odpowiednimi danymi wejściowymi do testu, a ponieważ niepuste ciągi znaków po prostu się udają, a pętla while zapętla się na zawsze.
Zamiast tego możesz spróbować
while false; do
echo "hello"
done
ewentualnie zastępując false
z true
. A może chcesz użyć (( ))
:
while (( 0 )); do
echo "hello"
done
Które będą się zachowywać jak większość języków, gdzie 0 oznacza błąd / fałsz, a 1 oznacza sukces / prawda.
0
i 1
nie są puste ciągi. Nowi programiści powłoki często piszą if [ 1=2 ]
zamiast if [ 1 = 2 ]
i zastanawiają się, dlaczego to pierwsze jest zawsze prawdziwe. To prawda, ponieważ jest to pojedynczy argument i nie jest pustym ciągiem.
Wartość 0 nie działa tutaj jako stała liczbowa, ale jako ciąg znaków. Wszystkie te testy są równoważne pod względem efektu pomyślnego zakończenia połączenia:
[ A ]
[ "XYZ" ]
[ 0 ]
generują one status zakończonego niepowodzeniem:
[ ]
[ "" ]
istnieje niepusty argument, który daje logiczną wartość prawda. To pozwala ci robić takie rzeczy jak:
if [ $UNDER_NUCLEAR_ATTACK ] ; then
launch-missiles -a $DRY_RUN # $DRY_RUN set to "-n" during testing
fi
Zmienna UNDER_NUCLEAR_ATTACK
jest ustawiona na dowolną niepustą wartość, aby wskazać wartość true, lub jest nieustawiona lub pusta, aby wskazać wartość false.
Możemy zastosować !
operatora do odwrócenia logiki:
[ ! a ] # fails: a is nonblank so true; and not true is false.
[ ! ] # succeeds: blank is false, not blank is true.
Aby ocenić warunek numeryczny, musisz użyć numerycznych operatorów testowych:
while [ $A -gt $B ] ; do ...
Jeśli A
i B
zawierają ciągi, które wyglądają jak dziesiętne liczby całkowite, są one porównywane jak liczby, a jeśli A
jest większe niż B
, pętla wykonuje się. Załóżmy więc, że UNDER_NUCLEAR_ATTACK
nie jest to boolean typu łańcuchowego, który jest pusty lub niepusty, ale w rzeczywistości boolean numeryczny, który ma wartość 0
(false) lub inną wartość (true). W takim przypadku napisalibyśmy test w ten sposób:
if [ $UNDER_NUCLEAR_ATTACK -ne 0 ] ; then ...
Konstrukcja if / then sprawdza, czy status wyjścia listy poleceń wynosi 0 (ponieważ 0 oznacza „sukces” zgodnie z konwencją UNIX), a jeśli tak, wykonuje jedno lub więcej poleceń.
Krótko mówiąc, zwracasz wynik testu równy zero.
[
dostaje tylko jeden argument ( ]
oczywiście z wyłączeniem ), to kończy się ze statusem zero, jeśli argument nie jest pusty, a niezerowy, jeśli tak jest. Na przykład [ 1 ]
zwróci również kod wyjścia z 0
.
Wartość 0 jest uważana za prawdę dla pętli while, dlatego warunek dla pętli while jest prawdziwy, a zatem ciągłe wyświetlanie pętli nieskończonej. Jest to prawdą, jeśli zamieniamy 0 na 1, ponieważ każda liczba całkowita, którą zapisujemy między warunkiem, zwróci true
[ ]
(bez argumentu) i[ "" ]
(z jednym pustym argumentem) nie udaje się.