W każdym języku dłuższe programy można organizować korzystajac z funkcji i plików z funkcjami nie inaczej jest w Bashu, co prawda nie jest językiem wspierajacym pisanie obiektowe - ale kto tego potrzebuje pisząc w gruncie rzeczy proste skrypty powłoki?
To coś w rodzaju podprogramów. Stosuje się je gdy w naszym skrypcie powtarza się jakaś grupa poleceń (po co pisać je kilka razy), skoro można to wszystko umieścić w funkcji.
Do danej funkcji odwołujemy się podając jej nazwę, a wykonane zostanie wszystko co wpisaliśmy między nawiasy {
}
,
skraca to długość skryptu, a więc ilość miejsc w których moglismy się pomylić, oprócz tego ułatwia zrozumienie kodu
(nie trzeba czytać wielokrotnietego samego).
W Bashu są dwa równoważne sposoby definiowania funkcji
Pierwszy sposób | Drugi sposób |
---|---|
function nazwa_funkcji {
polecenie1
polecenie2
polecenie3
}
Podpowiedź Pierwszy sposób deklaracji funkcji
jest znacznie czytelniejszy,
ponieważ nazwę funkcji umieszczamy
po słowie kluczowym |
nazwa_funkcji() {
polecenie_1
polecenie_2
polecenie_3
}
Ostrzeżenie O mniejszej czytelności drugiego sposobu może świadczyć fakt wykorzystania go podczas realizacji ataku bash fork-bomb. |
Przykład
#!/bin/bash
function napis {
echo "To jest napis"
}
napis
W powyższym przykładzie mamy zdefiniowaną funkcję o nazwie napis
.
Odwołujemy się do niej podając jej nazwę - wykonane zostaną wtedy wszystkie polecenia, jakie jej przypiszemy (znajdujące się w ciele funkcji).
johny@ThinkPad:~$ function napis {
> echo "To jest napis"
> }
johny@ThinkPad:~$
johny@ThinkPad:~$ napis
To jest napis
Ostrzeżenie
Niestety częściej stosowany do deklaracji funkcji jest sposób bez słowa kluczowego function
- wynika to z tego,
że jest w nim mniej pisania i jest on bardzo podobny do tego znanego z języka ANSI C.
Przekazanie parametrów do funkcji następuje dokładnie tak samo jak do każdego polecenia które jest w naszym skrypcie, realizuje się to podając po nazwie funkcji dodatkowe argumenty.
nazwa_funkcji parametr_1 parametr_2
Przykład
#!/bin/bash
funkcja_z_parametrami() {
echo "Przekazano $# parametrów"
echo "Parametr $1"
echo "Parametr $2"
}
funkcja_z_parametrami "param1" "param2"
johny@ThinkPad:~$ funkcja_z_parametrami "param1" "param2"
Przekazano 2 parametrów
Parametr param1
Parametr param2
Ostrzeżenie
Zmienna specjalna $0
przechowujaca nazwę skryptu nie jest dostępna!
Choć na pierwszy rzut oka wydaje się, że powinna przechowywać nazwę funkcji.
Funkcje moga się znajdować w innym pliku, co uczyni nasz skrypt bardziej przejrzystym i wygodnym.
Definiowanie pliku zawierającego funkcje nie jest trudne wystarczy utworzyć skrypt (dokładnie taki sam jak każdy do tej twory tworzony) i dołączyć go do naszego głownego „programu”.
Podpowiedź
Dołączanie pliku można zrealizować na dwa sposoby - poprzez skorzystanie z polecenia source lub polecenia . (kropka).
Efekty uzyskane za ich pomocą sa identyczne.
Do pliku o nazwie: naszplik_z_funkcjami.sh
wpisujemy dwie funkcje:
function nazwa_funkcji {
polecenie_1
}
nazwa_funkcji2() {
polecenie_1
}
następnie wczytujemy ten plik jednym z dwóch sposobów
Pierwszy sposób | Drugi sposób |
---|---|
source ~/naszplik_z_funkcjami.sh
Podpowiedź Wczytanie pliku z funkcjami przy wykorzystaniu polecenia source jest czytelniejsze. |
. ~/naszplik_z_funkcjami.sh
|
i możemy wywołać polecenia: nazwa_funkcji
i nazwa_funkcji2
Podpowiedź
Funkcje z pliku możemy wczytać do:
- bieżącej interaktywnej powłoki,
- do skryptu uruchomionego z linii poleceń
Przykład
Utwórzmy plik plik_z_funkcja.sh
którego zawartość jest taka jak poniżej:
#!/bin/bash
function nasza_funkcja {
echo -e 'Właśnie użyłeś funkcji o nazwie "nasza_funkcja".\a'
}
następnie wczytajmy plik plik_z_funkcja.sh
do aktualnej powłoki i wywołamy funkcje nasza_funkcja
johny@ThinkPad:~$ echo "Echo test"
Echo test
johny@ThinkPad:~$ source plik_z_funkcja.sh
johny@ThinkPad:~$ nasza_funkcja
Właśnie użyłeś funkcji o nazwie "nasza_funkcja".
Wszędzie tam, gdzie musimy użyć pojedynczej instrukcji, możemy zastosować blok instrukcji, czyli ciąg instrukcji ujęty w nawiasy klamrowe lub zwykłe.
{
ciąg poleceń
...
}
W przypadku nawiasów klamrowych polecenia są wykonywane w bieżącej powłoce i środowisku. Wartością takiego bloku jest wartość ostatniej wykonanej instrukcji.
Przykład:
#!/bin/bash
if true && { false;false;true } ; then
echo TRUE
fi
Powyższy skrypt wypisze TRUE
, ponieważ ostatnia instrukcja zwraca wartość 0 (true)
.
(
ciąg poleceń
...
)
Dla poleceń w nawiasach zwykłych tworzona jest nowa powłoka.
Wartością zwracaną jest kod ostatniej instrukcji bądź wartość zwrócona przez
komendę exit
(notabene to jest zwrócenie wartości ustalonej wcześniej).
Przykład
if true && (false;false;exit 0) ; then
echo TRUE
fi
Powyższy skrypt wypisze TRUE
, ponieważ ostatnia instrukcja zwraca wartość 0 (true)
.