Kup ten Shell Scripting Tutorial jako PDF za jedyne $5
Test jest używany przez praktycznie każdy napisany skrypt powłoki. To może nie wydawać się w ten sposób, ponieważtest
nie jest często wywoływany bezpośrednio. test
jest częściej wywoływany jako
if SPACE
Test is a simple but powerful comparison utility. For full details, run man test
w twoim systemie, ale oto kilka zastosowań i typowych przykładów.
Test jest najczęściej wywoływany pośrednio przez instrukcje if
iwhile
. Jest to również powód, dla którego napotkasz trudności, jeśli stworzysz program o nazwie test
i spróbujesz go uruchomić, ponieważ ta wbudowana powłoka zostanie wywołana zamiast twojego programu!
Składnia dla if...then...else...
jest:
if then # if-codeelse # else-codefi
if ; then # do somethingfi
Możesz również użyć elif
, jak to:
if ; then echo "Something" elif ; then echo "Something else" else echo "None of the above"fi
Spróbuj następujący wycinek kodu, przed uruchomieniem ustaw zmienną X na różne wartości (spróbuj -1, 0, 1, hello, bye, itp). Możesz to zrobić w następujący sposób (dzięki Dave'owi za wskazanie potrzeby wyeksportowania zmiennej, jak zauważono w Zmienne - Część I.):
$ X=5$ export X$ ./test.sh ... output of test.sh ...$ X=hello$ ./test.sh ... output of test.sh ...$ X=test.sh$ ./test.sh ... output of test.sh ...
Potem spróbuj ponownie, podając $X
jako nazwę istniejącego pliku, takiego jak /etc/hosts
.
test.sh
Zauważ, że możemy użyć średnika (;
) do połączenia dwóch linii razem. Robi się to często, by zaoszczędzić trochę miejsca w prostych instrukcjach if
.
Odwrotny ukośnik (\
) służy podobnemu, lecz przeciwnemu celowi: mówi powłoce, że to nie jest koniec wiersza, lecz że następny wiersz powinien być traktowany jako część bieżącego wiersza. Jest to przydatne dla czytelności. Zwyczajem jest wcięcie następującego wiersza po odwrotnym ukośniku (\
) lub średniku (;
).
Na przykład, średnik (;
) jest często używany w ten sposób do łączenia słów kluczowych if
i then
:
if ; then echo "X is a file which is newer than /etc/passwd"fi
natomiast odwrotny ukośnik (\
) jest używany do rozdzielenia jednowierszowego polecenia na dwa wiersze w pliku skryptu powłoki, w celach czytelności:
&& \ echo "X is a file which is newer than /etc/passwd"
Jak widzimy z tych przykładów, test
może wykonywać wiele testów na liczbach, łańcuchach i nazwach plików.
Istnieje prostszy sposób pisania instrukcji if
: Polecenia &&
i ||
podają kod, który należy uruchomić, jeśli wynik jest, odpowiednio, prawdziwy lub fałszywy.
Ta składnia jest możliwa, ponieważ istnieje plik (lub budulec powłoki) o nazwie Konstrukcja jest zalecana dla pętli while i trywialnych kontroli poprawności, z którymi nie chcesz nadmiernie rozpraszać czytelnika.
Zauważ, że kiedy ustawiasz X na wartość nienumeryczną, pierwsze kilka porównań skutkuje komunikatem:
Dzieje się tak, ponieważ porównania -lt, -gt, -le i -ge są zaprojektowane tylko dla liczb całkowitych i nie działają na łańcuchach. Porównania łańcuchów, takie jak !=
, z radością potraktują "5" jako łańcuch, ale nie ma sensownego sposobu traktowania "Hello" jako liczby całkowitej, więc porównania liczb całkowitych narzekają.
Jeśli chcesz, by twój skrypt powłoki zachowywał się z większym wdziękiem, będziesz musiał sprawdzić zawartość zmiennej przed jej przetestowaniem - może coś w tym stylu:
W ten sposób możesz echo
bardziej znaczący komunikat dla użytkownika, i wyjść z wdziękiem. Zmienna $?
jest wyjaśniona w Zmienne - część II, a grep
jest skomplikowaną bestią, więc zaczynamy: grep
znajduje wiersze tekstu, które zawierają cyfry (0-9) i ewentualnie inne znaki, więc daszek (^
) w grep
znajduje tylko te wiersze, które nie składają się wyłącznie z cyfr. Następnie możemy podjąć działania odwrotne (działając na niepowodzenie, a nie na sukces). Ok. >/dev/null 2>&1
kieruje wszelkieoutput lub błędy do specjalnego urządzenia "null", zamiast na ekran użytkownika.
Wielkie podziękowania dla Paula Schermerhorna za poprawienie mnie - ta strona twierdziła, że grep -v
będzie działać, ale jest to wyraźnie zbytnie uproszczenie.
Możemy używać test w pętlach while, jak poniżej:
test2.sh
#!/bin/shX=0while do echo "Enter some text (RETURN to quit)" read X echo "You said: $X"done
Ten kod będzie pytał o dane wejściowe, dopóki nie naciśniesz RETURN (X ma zerową długość).Podziękowania dla Justina Heatha za wskazanie, że skrypt nie działa - brakowało mi cudzysłowów wokół $X w while
. Bez tych cudzysłowów nie ma nic do testowania, gdy $X jest pusty.
Alexander Weber zauważył, że uruchomienie tego skryptu zakończy się nieporządnie:
Można to uporządkować za pomocą innego testu wewnątrz pętli:
#!/bin/shX=0while do echo "Enter some text (RETURN to quit)" read X if ; then echo "You said: $X" fidone
Zauważ także, że użyłem dwóch różnych składni dla if
deklaracji na tej stronie. Są to:
if then echo "X is less than zero"fi.......... and ........if ; then echo "You said: $X"fi
Musisz mieć przerwę między instrukcją if
a konstrukcją then
. Może to być średnik lub nowa linia, nie ma znaczenia która, ale musi być jedna lub druga między if
a then
.Byłoby miło po prostu powiedzieć:
if echo "You said: $X"
ale then
i fi
są absolutnie wymagane.
Powrót: Loops Next: Case