Programowanie w Shellu (index)
Zbadać zachowanie polecenia test.
$ help test | less $ man test $ test -r plik1 (sprawdzamy nieistniejący plik) $ echo $? (sprawdzenie kodu powrotu) $ test -d /etc (sprawdzenie istnienia katalogu) $ echo $? (sprawdzenie kodu powrotu) $ test -d /etc && echo "to katalog" $ if [ -d /etc ] ; then echo "to katalog" ; fi $ test "abc" = "def" (porównanie napisów) $ echo $? (sprawdzenie kodu powrotu) $ test -f /etc/passwd -a -r /etc/passwd (czy plik zwykły i czy mamy prawo czytania $ echo $? (sprawdzenie kodu powrotu) $ printenv PLIK_LOG (sprawdzenie stanu zmiennej) $ if [ -z "${PLIK_LOG}" ] ; then PLIK_LOG="sesja.log" ; fi (ustawienie zmiennej, jeżeli jest pusta) $ printenv PLIK_LOG (sprawdzenie wyniku podstawienia)
Stworzyć plik bc.sh postaci:
#!/bin/bash # # bc.sh # # Nakładka na polecenie "bc", zwracająca wynik działania. if [ "$1" = "-p" ] ; then PRECISION=$2 shift 2 # przesuniecie numeracji argumentow else PRECISION=2 # wartosc domyslna fi bc -q -l << EOF scale=${PRECISION} $* quit EOF exit 0
Uruchomić skrypt poleceniami:
$ ./bc.sh 12/456 $ ./bc.sh -p 6 12/456
Zapoznać się z możliwościami kalkulatora bc.
Stworzyć plik miesiac.sh postaci:
#!/bin/bash # # miesiac.sh # # Skrypt tlumaczacy skrot na pelna nazwe miesiaca. # Wykorzystanie konstrukcji warunkowej "case". echo -n "Podaj numer lub skrot miesiaca: " read MIESIAC case ${MIESIAC} in 1|01|Jan*) echo "${MIESIAC} to January (styczen)" ;; 2|02|F*) echo "${MIESIAC} to February (luty)" ;; 3|03|Mar*) echo "${MIESIAC} to March (marzec)" ;; 4|04|Ap*) echo "${MIESIAC} to April (kwiecien)" ;; 5|05|May) echo "${MIESIAC} to May (maj)" ;; 6|06|Jun*) echo "${MIESIAC} to June (czerwiec)" ;; 7|07|Jul*) echo "${MIESIAC} to July (lipiec)" ;; 8|08|Au*) echo "${MIESIAC} to August (sierpien)" ;; 9|09|S*) echo "${MIESIAC} to September (wrzesien)" ;; 10|O*) echo "${MIESIAC} to October (pazdziernik)" ;; 11|N*) echo "${MIESIAC} to November (listopad)" ;; 12|D*) echo "${MIESIAC} to December (grudzien)" ;; *) echo "Nieznany miesiac";; esac
Uruchomić skrypt poleceniem: ./miesiac.sh
Typy plików [ -f plik1 ] (plik1 istnieje i jest plikiem zwyklym) [ -d plik1 ] (plik1 istnieje i jest katalogiem) [ -b plik1 ] (plik1 istnieje i jest urządzeniem blokowym) [ -c plik1 ] (plik1 istnieje i jest urządzeniem znakowym) [ -h plik1 ] (plik1 istnieje i jest dowiązaniem symbolicznym) [ -p plik1 ] (plik1 istnieje i jest łączem nazwanym [pipe]) [ -L plik1 ] (plik1 istnieje i jest łączem nazwanym [pipe]) [ -S plik1 ] (plik1 istnieje i jest gniazdem [socket]) [ -t 1 ] (standardowym wyjsciem jest terminal) Prawa dostępu do plików (wybrane) [ -r plik1 ] (plik1 istnieje i mamy do niego prawo czytania) [ -w plik1 ] (plik1 istnieje i mamy do niego prawo pisania) [ -x plik1 ] (plik1 istnieje i mamy do niego prawo wykonywania) [ -s plik1 ] (plik1 istnieje i ma rozmiar wiekszy niz zero bajtow) Właściwości plików [ -e plik1 ] (plik1 istnieje) [ -s plik1 ] (plik1 istnieje i ma rozmiar większy niż zero) [ plik1 -nt plik2 ] (plik1 jest nowszy niż plik2) [ plik1 -ot plik2 ] (plik1 jest starszy niż plik2) [ plik1 -ef plik2 ] (plik1 i plik2 są wzajemnie dowiązaniami sztywnymi)
Łancuchy dobrze jest umieszczać w cudzysłowach. Wtedy nawet pusta zmienna (lub nieustawiona) bedzie dobrze przetworzona.
[ s1 ] (łańcuch s1 nie jest pusty) [ -n s1 ] (długość łańcucha s1 nie jest zerowa) [ -z s1 ] (długość łańcucha s1 jest zerowa) [ s1 = s2 ] (łańcuchy s1 i s2 są identyczne; ODSTEPY!) [ "${ZMIENNA1}" = "${ZMIENNA2}" ] (stosowanie cudzysłowu) [ s1 != s2 ] (łańcuchy s1 i s2 nie są identyczne) [ s1 < s2 ] (łańcuch s1 sortuje się przed s2) [ s1 > s2 ] (łańcuch s1 sortuje się po s2)
[ int1 -eq int2 ] (=, equal to) [ int1 -gt int2 ] (>, greater than) [ int1 -ge int2 ] (>=, greater than or equal to) [ int1 -lt int2 ] (<, less than) [ int1 -le int2 ] (<=, less than or equal to) [ int1 -ne int2 ] (<>, not equal to)
[ ! expr1 ] (not) [ expr1 -a expr2 ] (and) [ expr1 -o expr2 ] (or)
polecenie1 && { polecenie2 ; polecenie3 ;} Forma równoważna z if jest dłuższa: polecenie1 if [ $? -eq 0 ] ; then polecenie2 polecenie3 fi
polecenie1 || polecenie2 Forma równoważna z if: polecenie1 if [ $? -ne 0 ] ; then polecenie2 fi
Kod powrotu 0 polecenia oznacza true (prawdę). Zwykle polecenie to instrukcja test w postaci z nawiasami kwadratowymi [ ... ].
if polecenie ; then lista poleceń elif polecenie ; then (opcja) lista poleceń else (opcja) lista poleceń fi if polecenie ; then polecenie ; fi (postać minimalna) if polecenie ; then polecenie ; else polecenie ; fi if polecenie ; then polecenie ; elif polecenie ; then polecenie ; fi if polecenie ; then polecenie elif polecenie ; then polecenie elif polecenie ; then polecenie elif polecenie ; then polecenie else polecenie ; fi (ta postać może zastąpić instrukcję "case")
Generalnie instrukcja case nie jest polecana w różnych językach programowania, ale w shellu się przydaje. Zawsze powinno się umieszczać na końcu akcję domyślną.
case ${ZMIENNA} in wartosc1) (ważna jest kolejność podawanych warunków) lista poleceń ;; wartosc2|wartosc3) (można podać kilka wzorców) lista poleceń ;; *) (można używać metaznaków) polecenia domyślne (jako ostatnie) ;; esac
Zamiast wyrażenia ${ZMIENNA} można użyć każdego wyrażenia, które daje w wyniku napis, np. wynik jakiegoś polecenia $(ls x*).
help read (pomoc dla polecenia wewnętrznego powłoki) read LINE (wczytanie całego wiersza ze stdin do zmiennej LINE) read (wczytanie wiersza do zmiennej REPLY) read ZMIENNA1 ZMIENNA2 ZMIENNA3 (wczytanie kolejnych napisów do ZMIENNA1, ZMIENNA2, a reszty do ZMIENNA3) Typowe zastosowanie w skrypcie: echo -n "Podaj napis: " read NAPIS Można jeszcze prościej (opcja [-p prompt]): read -p "Podaj napis: " NAPIS Można wczytywać do zmiennych dane z pól oddzielonych innym znakiem niż te ze zmiennej IFS (opcja [-d delim]): read -d ":" POLE1 POLE2 POLE3