Zmienne definiuje się używając składni zmienna=wartosc
lub w przypadku zmiennych liczbowych let zmienna=liczba
, np.
$ napis=``Ala ma kota''
$ let wynik=10
Zmienne środowiskowe (globalne) tworzymy poleceniem export
.
$ export zmienna
$ export PATH=$PATH:.
Nazwa zmiennej może składać się z dowolnych liter, cyfr (cyfra nie może być pierwszym znakiem nazwy zmiennej) oraz znaku podkreślenia.
Wartość umieszczoną w zmiennej wydobywamy umieszczając $ przed nazwą zmiennej
$ echo $napis
$ Ala ma kota
$ echo $HOME
$ /home/student
$ echo $wynik
$ 10
W powłoce Bash mamy do dyspozycji tablice jednowymiarowe. Nie muszą one być deklarowane. Do poszczególnych elementów tablicy
odwołujemy sie poprzez nawiasy kwadratowe ${zmienna[indeks]}
$ kolor[1]=bialy
$ kolor[2]=czarny
$ kolor[3]=zielony
$ echo Kolor pierwszy $kolor[1]
$ echo Wszystkie kolory $kolor[*]
Tablice indeksowane są liczbami całkowitymi począwszy od zera.
Automatyczne przypisanie kolejnych wartości do tablicy uzyskujemy wpisując zmienna=(wartosc1 wartosc2 ... wartoscN)
, np.
$ dzien=(poniedzialek wtorek sroda czwartek piatek sobota niedziela)
$ echo $dzien[6]
$ echo Dni tygodnia: $dzien[8]
$ dzien[0]=Monday
Liczbę elementów tablicy uzyskujemy wyrażeniem ${#zmienna[*]}
$ echo Ilosc dni tygodnia = $#dzien[*]
Wyrażenie ${#zmienna[indeks]}
poda ilość znaków zawartych w elemencie tablicy i podanym indeksie.
$ echo Slowo $dzien[1] zawiera $#dzien[1] znakow
Polecenie unset zmienna
usuwa podaną zmienną. Chcąc usunąc wybrany element tablicy nalezy wykonać unset tablica[index]
.
$ unset kolor
$ unset dzien[4]
Zmienna $*
$ zawiera listę wszystkich argumentów z jakimi został wywołany skrypt, zmienna $#
podaje liczbę tych argumentów, zmienna $0
zawiera nazwę skryptu, zaś zmienne $1
, $2
, $3
, itd.
zawierają kolejne argumenty, np.:
#!/bin/bash echo Nazwa skryptu=$0 echo Podales $# argumentow echo Oto one: $* echo Argument 1 = $1 echo Argument 2 = $2
Powłoka tcsh pozwala na wykonywanie prostych operacji arytmetycznych na liczbach całkowitych za pomocą instrukcji let.
Przykład:
$ let suma=2+2
$ echo $suma
$ 4
$ let liczba=$suma*2
$ echo $liczba
$ 8
Składnia polecenia let
pozwala na używanie zmiennych liczbowych bez konieczności poprzedzania ich znakiem $
.
$ let liczba=suma*suma+3
$ let suma++
Dostępne operatory oraz priorytet ich wykonywania są takie same jak w języku C (Zobacz tabelę 1).
Równoważne użyciu polecenia let
jest zastosowanie (( wyrażenie ))
.
Przykłady:
$ a=$((1+2))
$ a=$(($a*$a))
$ a=$((a+1))
$ ((a++))
Proste operacje arytmetyczne można także wykonywać za pomocą instrukcji expr
.
Obliczenia o precyzji zmiennopozycyjnej (dla liczb rzeczywistych) można wykonywać za pomocą kalkulatorów bc
lub dc
.
Wyrażenia warunkowe realizowane są za pomocą [ wyrażenie ]
lub poprzez polecenie test
.
Wartością zwracana jest kod (status programu) 0 w przypadku gdy wyrażenie jest prawdziwe lub 1 gdy wyrażenie jest fałszywe.
Porównywanie napisów odbywa się za pomocą operatorów ==
, !=
, <
i >
.
$ [ $SHELL == /bin/bash ] && echo Uzywasz powloki Bash
$ test $USER != root ] && echo Nie jestes administratorem
Porównując liczby całkowite należy skorzystać z operatorów -eq
((ang. equal) - równe), -ne
((ang. not equal) - nie równe), -lt
((ang. less then) - mniejsze niż),
-gt
((ang. greater than) - większe niż), -le
((ang. less equal) - mniejsze równe) i -ge
((ang. greater equal) - większe równe).
$ [ $RANDOM -lt 16384 ] && echo Reszka
$ test `cat /etc/passwd | wc -l` -gt 100 && echo Uzytkownikow jest wiecej niz 100
Wyrażenie warunkowe może tez sprawdzać atrybuty plików:
-e
- plik istnieje, -f
jest zwykłym plikiem, -d
jest katalogiem, -r
jest plikiem do odczytu, -w
- jest plikiem do zapisu, x
- plik można uruchomić.
$ [ -e /etc/passwd ] && echo Plik /etc/passwd istnieje
$ test -d /etc/passwd && echo Plik /etc/passwd jest katalogiem
Dostępne mamy też operatory &&
(AND), ||
(OR) oraz zaprzeczenie !
(NOT) pozwalające łączyć wyrażenia warunkowe w bardziej złożone warunki.
W takim przypadku złożone wyrażenie logiczne należy umieścić w dodatkowych nawiasach [].
$ [[ $(($RANDOM%2)) -eq 1 && ! $USER == root ]] && echo Warunek jest spelniony
$ test ! -w /etc/passwd || $USER != root && echo Nie masz uprawnien do modyfikcaji /etc/passwd lub nie jestes root-em.
Wyrażenia warunkowe znajdują zastosowanie wraz z instrukcją if oraz pętlą while).
Składnia warunku:
if wyrażenie;
then
instrukcje
fi
Gdy wyrażenie jest prawdziwe (zobacz wyrażenia warunkowe) wówczas wykonywane są instrukcje pomiędzy słowem then i fi.
Przykład:
#!/bin/bash if [ $# -eq 0 ]; then echo "Nie podałeś żadnych argumentów " fi exit 0
Bardziej rozbudowane wyrażenie warunkowe:
if wyrażenie;
then
instrukcje
else
instrukcje 2
fi
Instrukcje zawarte w bloku rozpoczynającym się od else są wykonywane gdy wyrażenie nie jest spełnione. Np.:
#!/bin/bash if [ $# -eq 0 ]; then echo "Nie podałeś żadnych argumentów. " echo "Podaj liczbe calkowita " echo "Sprobuj: $0 liczba" exit 1 fi if [ $1 -lt 0 ]; then echo Liczba $1 jest mniejsza od zera else echo Liczba $1 jest wieksza lub równa 0 fi exit 0
Przykład - skrypt o nazwie rzut.sh wyświetlający słowo Orzeł lub Reszka z prawdopodobieństwem 1/2.
#!/bin/bash if [ $(($RANDOM%2)) -eq 1 ]; then echo "Reszka" else echo "Orzeł" fi
Przykład - skrypt o nazwie podglad.sh który dla danego w argumencie pliku wyświetla jego zawartość za pomocą less, zaś jeżeli podany argument jest nazwą pliku wówczas wyświetlana jest zawartość tego katalogu.
#!/bin/bash if [ $# -lt 1 ]; then echo "Podaj plik lub katalog jako argument." echo "Uzycie: $0 plik" exit 1 fi if [ -f $1 ]; then less $1 else if [ -d $1 ]; then ls -l $1 else echo "Blad: $1 nie jest plikiem ani katalogiem" fi fi
Pętla for wykonuje zadane instrukcje tyle razy ile jest elementów na podanej liście.
for zmienna in lista;
do
instrukcje
done
W każdej iteracji kolejny element z listy jest podstawiany do zmiennej.
Przykład uzycia w linii komend:
dla każdego pliku w bieżącym katalogu wyświetli komunikat o ilości zajmowanych bajtów.
Przykład - skrypt zamieniający w nazwach plików duże litery na małe.
#!/bin/bash if [[ $# -eq 0 || $1 == "-h" || $1 == "--help" ]]; then echo "Uzycie: $0 [-h] plik..." echo "Zamienia w nazwach podanych plikaow duze litery na male (np. Plik.TXT na plik.txt)." echo "Opcja -h wyswietla pomoc." exit 1 fi for plik in $* do if [ -e $plik ]; then nowy_plik=$(echo $plik | tr '[A-Z]' '[a-z]') if [ $plik != $nowy_plik ]; then echo "Zamieniam: $plik na $nowy_plik" mv $plik $nowy_plik fi else echo "Blad: $plik - nie ma takiego pliku" fi done
Powłoka Bash umożliwia także użycie pętli for znanej z języka C.
for (( wyrażenie1 ; warunek ; wyrażenie2 ))
do
instrukcje
done
Wszystkie instrukcje są wykonywane dopóki warunek jest spełniony.
Początkowe wyrażenie1 jest uruchomione tylko raz przed rozpoczęciem pętli, zazwyczaj służy do zainicjowania zmiennych.
Końcowe wyrażenie2 jest wykonywane na końcu każdej iteracji, zazwyczaj używane jest do zwiększenia (lub zmniejszenia) pewnego licznika.
Przykład - skrypt wyznaczający silnię:
#!/bin/bash if [[ $# -eq 0 || $1 == "-h" || $1 == "--help" ]]; then echo "Uzycie: $0 [-h] liczba" echo "Oblicza silnie podanej liczby." echo "Opcja -h wyswietla pomoc." exit 1 fi silnia=1; for (( i=2 ; i<=$1 ; i++ )) do let silnia=silnia*i; done echo "Silnia wynosi $silnia"
Przykład - wielokrotne losowanie kostką:
#!/bin/bash if [[ $1 == "-h" || $1 == "--help" ]]; then echo "Rzut kostka" echo "Uzycie: $0 [-h] liczba" echo "Wyswietla wynik rzutu kostka powtorzenoge zadana liczbe razy." echo "Opcja -h wyswietla pomoc." exit 1 fi ile=1 if [ $# -gt 0 ]; then ile=$1 ;fi for (( i=1 ; i<=ile ; i++ )) do wynik=$(($RANDOM%6+1)) echo $wynik done
Składnia pętli while:
while warunek
do
instrukcje
done
Podane instrukcje są wykonywana dopóki warunek jest prawdziwy.
Przykład - stoper, odlicza sekundy od rozpoczęcia działania skryptu:
#!/bin/bash if [[ $1 == "-h" || $1 == "--help" ]]; then echo "Stoper - po prostu uruchom bez argumentow." echo "Ctrl+C konczy odliczanie." echo "Opcja -h wyswietla pomoc." exit 1 fi let s=0 while true; do echo $s sleep 1 let s++ done
Instrukcja true zwraca zawsze wartość logiczną prawda. Analogicznie false daje odpowiedź negatywną.
Instrukcja case pozwala na wykonanie wybranych instrukcji w zależności od wartości przyjmowanej
przez pewną zmienną. Działanie bardzo podobne do instrukcji if jednak często wygodniejsze w użyciu, zwłaszcza gdy
mamy więcej niż dwie możliwości do wyboru.
case zmienna in
wartość_1)
instrukcje 1
;;
wartość_2)
instrukcje 2
;;
…
*)
instrukcje
;;
esac
Przykład - skrypt wyświetla menu:
#!/bin/sh while true do clear echo "============================" echo "[1] Wyświetl dzisiejszą datę" echo "[2] Wyswietl listę plików w bierzącym katalogu" echo "[3] Pokarz kalendarz" echo "[4] Pokarz listę zalogowanych uzytkownków" echo "[5] Zakończ" echo "============================" echo -n "Wybierz liczbę [1-5]: " read akcja case $akcja in 1) echo "Dzisiejsza data: `date`" ;; 2) echo "Lista plików w katalogu `pwd`" ls -l ;; 3) cal ;; 4) echo "Lista zalogowanych" ; who ;; 5) echo "Do widzenia" exit 0 ;; *) echo "Blad!!! Proszę wybrać wartość 1,2,3,4, lub 5"; esac echo "Wciśnij klawisz Enter" read done
Instrukcja exit kończy działanie skryptu.
Liczba całkowita umieszczona po instrukcji exit jest zwracana do powłoki jako wynik działania skryptu.
W przypadku poprawnego wykonania skrypt powinien kończyć się wyrażeniem exit 0. Gdy skrypt nie został wykonany poprawnie wówczas po słowie exit wstawiamy dowolną liczbę różną od zera (wartość zwracanej liczby może w ten sposób sygnalizować rodzaj błędu który spowodował niepoprawne wykonanie skryptu). Wartość zwracana po słowie exit umieszczana jest w zmiennej $?.
Instrukcja read pozwala wczytać linie tekstu do podanej zmiennej.
Przykład:
#!/bin/bash echo Podaj imie i nazwisko read dane echo Witaj $dane
Możliwe jet też czytanie tekstu z pliku linia po linii, np.:
#!/bin/bash echo Podaj nazwe pliku do wyswietlenia read plik if [ ! -r $plik]; then echo "Nie moge czytac z pliku $plik" exit 1 fi cat $plik | while read linia do echo $linia done
W powłoce bash możliwe jest definiowanie funkcji, czyli wyodrębnionych podprogramów oznaczonych pewną unikatową nazwą.
nazwa_funkcji( )
{
instrukcje do wykonania
return
}
Funkcja wykonywana jest w momencie gdy pojawi się wywołanie jej nazwy.
Przykład:
#!/bin/sh pomoc() { echo "Wyswietla liste i liczbe zalogowanych uzytkonikow" echo "Opcje:" echo "-h pomoc" echo "-l liczba zalogowanych użytkoników" echo "-w lista zalogowanych użytkoników" return } # lista niepowtarzajacych sie nazw zalogowanych uzytkownikow lista() { users=( `who | cut -f 1 -d ' ' | sort | uniq ` ) return } case $1 in "-h") pomoc ;; "-l") lista echo "Liczba zalogowanych uzytkonikow = ${#users[*]} " ;; "-w") lista echo "Lista uzytkownikow: ${users[*]}" ;; *)Ψpomoc ;; esac
Do funkcji możemy przekazać argumenty dodając je przy wywołaniu po nazwie funkcji. Kolejne argumenty umieszczone są w zmiennych $1, $2, $3, itd. Ilość argumentów dana jest poprzez $#, lista wszystkich argumentów zawarta jest w zmiennej $* a zmienna $0 zawiera nazwe funkcji.
#!/bin/sh funkcja() { echo "Argumenty funkcji $*" echo "Ilość argumentów funkcji $#" return 0 } echo "Argumenty skryptu $*" echo "Ilość argumentów skryptu $#" echo Uruchamiam funkcje z argumentami: raz dwa trzy funkcja raz dwa trzy echo Uruchamiam funkcje z argumentami będącymi nazwami plików z bierzącego katalogu funkcja * exit 0
Zmienne użyte wewnątrz funkcji maja zakres globalny, tzn. ich wartość jest dostępna poza funkcją (np. zmienna users z pierwszego przykładu w tym paragrafie).
Chcąc ograniczyć czas życia zmiennej wyłącznie do obszaru zdefiniowanego przez funkcję należy zadeklarować zmienną poprzedzając ja instrukcją local.
Używanie zmiennych lokalnych może uchronić przed wieloma trudnymi do wykrycia błędami, więc gdzie tylko jest to możliwe, wewnątrz funkcji należy je stosować.
Przykład:
#!/bin/sh funkcja() { local zmienna="Zmienna lokalna" echo "Jestem wewnątrz funkcji" echo "zmienna=$zmienna" return 0 } zmienna="Zmienna globalna" echo "Zmienna=$zmienna" funkcja echo "Zmienna=$zmienna" exit 0