LX-SCR-INFO-funkties
Updated 7/27/10 00:36
funkties
Als je regelmatig scripts schrijft, begin je te kopiëren van scripts die je reeds geschreven hebt. Dat is niet slecht, maar wel gevaarlijk. Je zou per ongeluk het reeds bestaande script wel eens kunnen verminken. Bovendien is het mogelijk dat je tijdens het 'cut and paste' proces een paar regels of karakters vergeet. Tenslotte werkt niet alle code zomaar overal.
Voor dit probleem is een function bibliotheek de perfecte oplossing.
Maar bash functions kun je ook gebruiken om je script gewoon overzichtelijker te maken.
En zodra je twee keer dezelfde code in één script gebruikt, spaar je tijd en plaats met functions.
Functions moet je plaatsen voor ze worden aangeroepen. Verder is er geen belemmering. Het is echter makkelijker en overzichtelijker alle functies te declareren aan het begin van een script.
- syntax
function <functionname> () {
<commando's>
}
Je kan een function beginnen met function; () is dan niet nodig.
Je kan een function beginnen met zijn naam;
het keyword function is dan niet nodig, de () wel.
In deze cursus gebruik ik altijd de vorm: function <naam> { <commando's> }
Er zijn dus nergens ().
- voorbeeld
In dit voorbeeld wordt er een function aangeroepen die de laatste 5 regels van de /var/log/messages op scherm brengt.
#!/bin/bash
#
# whatwedo
#
function showlog {
clear
tail -n 5 /var/log/messages
}
# zolang root niet is ingelogd blijft de volgende until lus draaien
until w | grep "root"
do
showlog
sleep 5
done
- parameters
Funkties in bash werken graag met parameters. We herwerken het vorige voorbeeld ...
#!/bin/bash
#
# whatwedo2
#
function showlog2 {
# $1 = logfile to display
# $2 = aantal regels
# $3 = refresh time
clear
tail -n $2 $1
sleep $3
}
function timestamp {
echo $(date +"%Y%m%d%H%M")
}
# zolang root niet is ingelogd blijft de volgende until lus draaien
until w | grep "root"
do
showlog2 /var/log/messages 10 2
done
printf "root has logged in :"
timestamp
- library
Maak een file in je bin directory met als naam functions.lib. Deze file moet niet executable zijn, wel leesbaar vanaf je script.
Stop in functions.lib al je functions die je overal wil kunnen gebruiken.
Lees die dan vanaf je script
De naam en het path van de library kies je zelf!
functions.lib:
function showlog2 {
# $1 = logfile to display
# $2 = aantal regels
# $3 = refresh time
clear
tail -n $2 $1
sleep $3
}
function timestamp {
echo $(date +"%Y%m%d%H%M")
}
whatwedo3:
#!/bin/bash
#
# whatwedo3
#
# nu lezen we de function library in met het dot commando
. ~/bin/functions.lib
#
# zolang root niet is ingelogd blijft de volgende until lus draaien
until w | grep "root"
do
showlog2 /var/log/messages 10 2
done
printf "root has logged in :"
timestamp
- variabelen
Variabelen die gebruikt worden binnen een function zijn lokaal en wijzigen script variabelen met dezelfde naam niet:
#!/bin/bash
#
# fvar: een educatief script
# dat het gebruik van variabelen in functies toont
#
stad=Hasselt
provincie=Limburg
function mixup {
stad=Gent
provincie=OVL
echo $stad $provincie
}
echo script: $stad $provincie
echo function: $(mixup)
echo script: $stad $provincie
echo function: $(mixup)
Met als output:
$ fvar
script: Hasselt Limburg
function: Gent OVL
script: Hasselt Limburg
function: Gent OVL
- recursieve functions
Recursie is het oproepen van zichzelf in een routine.
Bekijk even het volgende probleem:
Als ik een kopieeropdracht uitvoer van een gigantische file, kan ik de vooruitgang volgen op een andere terminal met het commando ls -l. Dat moet ik dan regelmatig intikken. Als ik mijn leven makkelijker zou willen maken zou ik het volgende script kunnen construeren:
#!/bin/bash
#
# showls: toont de directory van parameter $1
#
clear
ls -l $1
sleep 5
showls
Maar, een script dat zichzelf aanroept, maakt telkens nieuwe processen aan, met als gevolg dat de computer vroeger of later vastloopt. En dat is een ramp voor mijn kopieeropdracht, met veel tijdverlies, of erger, tot gevolg.
Functions hebben dit probleem niet, omdat ze niet telkens een nieuw bash proces lanceren, maar de stack van bash kan nog wel overlopen!!! Als de stack overflowt heeft dat echter alleen effect op die bash die mijn script beheert. De andere processen kunnen gewoon door blijven lopen, of toch niet :-) ? Zoek dat misschien zelf eens op!
Het volgende script kan dus wel veel langer doorlopen dan het vorige:
#!/bin/bash
#
# fshowls: toont de directory van parameter $1
#
function showls {
clear
ls -l $1
sleep 5
showls
}
showls $1
De eenvoudigste oplossing voor het hogere probleem is echter het commando watch.
$ watch -n5 ls -l
- export
Je kan functions exporteren en ze dan gebruiken aan de bash prompt. functions hebben wat meer mogelijkheden dan aliassen. Een dergelijke function inclusief export plaats je het best in je .bashrc
fname {
echo "Foo"
}
export -f fname
- oefeningen
- Maak een function met als naam ohce (echo omgekeerd) die al zijn argumenten omgekeerd afdrukt. Gebruik dit in een script. (tip: man rev)
- Bekijk het voorbeeld "apester" in het hoofdstuk "parameters" opnieuw.
- Maak twee functions: leftstr en rightstr die een string respectievelijk links en rechts afknippen ter hoogte van karakternummer. string en karakternummer zijn de parameters waarmee de functions worden opgeroepen.
Illustreer je funktie met een voorbeeldscript.