Definíció
A függvények általában névvel ellátott kódszekvenciát jelentenek a programozási nyelvekben. A shell esetében is így van, mivel a nyelv interpretált, a függvény nevét és kódját felhasználás előtt, a program szövegében kell definiálni. Ez történhet a szkript elején vagy egy külön állományban, amelyet függvényhívás előtt beolvasunk.
A függvény kód szekvenciáját kapcsos zárójelek közt definiáljuk, a { }-ek közti részt a héj kód blokknak (code block) nevezi.
Ha külön állományban definiáljuk a függvényeket, akkor a . (dot) paranccsal kell őket az főprogramot tartalmazó állományba illeszteni.
A függvények úgy viselkednek mint egy-egy külön kis shell program. Argumentumaikat is ugyanúgy kapják (nem kell argumentumlistát definiálni) és a függvény testében az 1, 2, stb. változókkal érhetők el ($1, $2).
A függvény definíció szintaxisa:
function nev () {
#ide kerül a függvény kódja }
A nyitó kapcsos zárójel a név sorában is szerepelhet:
function nev () {
#ide kerül a függvény kódja }
Ugyanakkor a function kulcsszó akár el is hagyható, tehát a definíció ilyen is lehet:
nev () {
#ide kerül a függvény kódja }
Például:
function equal() {
if [ "$1" = "$2" ];then return 0
else
return 1 fi
}
Különböző héj szerkezetek
Fontos: a return parancs a függvény kilépési értékét küldi vissza, ez hívó héj ? változóját állítja be, ennek értéke lesz a return által visszaadott kód, és azt a $? hivatkozással érhetjük el a hívó szekvenciában, tehát nem eredmény visszatérítésre használjuk!
Így a függvény használata:
if equal "$a" "$b"
then
echo egyenloek fi
A függvények megosztják változóikat a hívó héjjal, vigyázni kell tehát a kilépési értékekre illetve a változómódosításra.
Ezek a megosztott változók un. globális változók. Ennek következtében a függvényben láthatóak a hívó szkript változói, és a a függvényben létrehozott változók láthatóak lesznek a hívó szkriptben.
Ha az equal függvényt egy equal.sh állományba írjuk, akkor a . paranccsal az alábbi módon használhatjuk az aktív héjban:
$. equal.sh
$equal "a" "b"
$echo $?
1
A . beolvassa a definíciót, és utána lehet használni ebből a héjból. Függvénydefiníciót törölni az unset parancsot használva lehet:
$unset equal
$equal "a" "b"
-bash: equal: command not found
$
Az unset két opciót fogad el, -v ha csak a megadott változóneveket, -f ha csak megadott függvényneveket akarunk törölni. Opció nélkül mindkettőt próbálja törölni.
A függvénydefiníciót megadhatjuk egyetlen parancssorban:
$ function hello () { echo "Helló" ; return 0; }
$ hello Helló
Ilyenkor az utolsó parancs után is meg kell jelennie a ; elválasztónak.
Bárhogyan adnánk meg a definíciót, annak meg kell jelennie a kódban a függvény használata előtt (a definíció bárhol lehet, nem kötelező a szkript elejére tenni)!
A függvények nem lehetnek üresek, tehát legalább egy parancsot kell tartalmazzanak.
Függvények érték visszatérítése
Az eredmények visszaadását a hívó szkriptnek az alábbi módszerekkel oldjuk meg:
1. globális változó beállítása
2. nyomtatás a függvényben és parancssor helyettesítés a hívásnál
Különböző héj szerkezetek
Az alábbi függvényt a getfname.sh állományban definiáljuk:
#visszaadja az állománynevet, levágva az extenziót
#egy bemeneti paramétere van
#ha több pont van a névben, az utolsótól a végéig vágja le
#a karaktereket
#ha nincs . , akkor a teljes nevet adja vissza function getfname()
{
#elhagyjuk az utolsó ponttól
#a név végéig terjedő szubsztringet echo "$1" | sed -r 's/(.+)(\.[^.]*)$/\1/' return
}
A sed parancs használatát lásd a parancsot bemutató fejezetben.
A függvény használata:
#!/bin/bash
. getfname.sh #függvény definíció betöltése fname="file.txt"
name=$(getfname $fname) echo $name
Az alábbi esetben viszont a függvényben létrehozott line változón keresztül tér vissza az érték (a függvénydefiníció a getline.sh fájlban található):
#egy sort olvas be és azt a line változóban adja vissza
#a főprogramnak vagy más függvénynek
#ha a felhasználó Ctrl-D-t üt be, akkor kilép
function getline {
line=""
if ! read -p "Kérek egy sztringet:" line then
echo "Olvasás hiba";
return 1 fi
return 0 }
Használata:
$. getline.sh
$ if getline ; then echo $line ; fi Kérek egy sztringet:piros
piros
$
Környezettel kapcsolatos kérdések
Különböző héj szerkezetek
A függvény megkapja a hívó héj munka könyvtárát, környezeti változóit. A függvényben létrehozott változók láthatóak lesznek a hívó héjban, és a függvény is látja az ott előzőleg létrehozott változókat.
Lokális változók használata
A Bash megengedi lokális változók használatát is. Ezeket a local kulcsszóval adjuk meg:
function teszt () {
local valtozo=3
local eredmeny=$(( valtozo * $1 )) echo $eredmeny
}
Ebben az esetben a valtozo és eredmeny változók nem lesz láthatóak a hívó héjban, még csak nem is írják felül az ott található ugyanolyan nevű változókat:
$ . teszt.sh
$ eredmeny=33
$ teszt 8 24
$ echo $eredmeny 33
$ echo $valtozo
$
Rekurzív hívások
Rekurzív hívás lehetséges. Azonban ha a rekurzív feldolgozás számításokat használ, amelyek paraméterként kell átadódjanak egyik szintről a másikra, meglehetősen nyakatekert kódot kapunk. Az alábbi függvény faktoriálist számol, és az eredményt egy fact nevű változóban téríti vissza:
#egy paraméterrel kell meghívni
#n! -t számol
function calc_fact1() {
if (( $1 == 0 )) ; then
fact=1 #ha n == 0 , akkor fact=1 return
else
calc_fact1 $(( $1 - 1 )) # (n-1)! marad a # fact-ban változoban
fact=$(( fact * $1 )) # fact n! lesz fi
return }
Ugyanez megoldható úgy is, ha az eredményt a ? változóban adjuk vissza, persze ezzel a $? -t nem rendeltetésének megfelelően használjuk. Az alábbi példában az n változót lokálisként használjuk (rekurzív hívások esetében ez a Bash tervezőinek ajánlata), így minden hívás esetében ismét létrejön:
function calc_fact() {
local n=$1 #n lokális if (( n == 0 )) ; then
Különböző héj szerkezetek
return 1 else
calc_fact $(( n - 1 )) # (n-1)!
return $(( $? * n )) # n!
fi }
Megjegyzendő, hogy a ? változóban a Bash esetében csak 255-nél kisebb egész számot lehet visszatéríteni (tehát annál nagyobb számokra a fenti függvény nem használható).
A rekurzió a héjban lassú, erőforrás igényes és ezért nem javasolt a használata.