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. testsł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ą 0ani nie 1są 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 falsez 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.
0i 1nie 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_ATTACKjest 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 Ai Bzawierają ciągi, które wyglądają jak dziesiętne liczby całkowite, są one porównywane jak liczby, a jeśli Ajest większe niż B, pętla wykonuje się. Załóżmy więc, że UNDER_NUCLEAR_ATTACKnie 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ę.