Baukastensystem
Teil 6: Funktionen und Module
Modularisierung
Mit Funktionen kann man ein Programm nicht nur kürzer und besser lesbar machen, bei ähnlichen Anwendungen kann man die Funktionen auch leicht in einem anderen Programm wiederverwenden. Wenn Sie eine Reihe von Funktionen geschrieben haben, sollten Sie sie in einzelnen Modulen zusammenfassen. Ein Modul enthält eine oder mehrere Funktionen aus verwandten Aufgabenbereichen wie zum Beispiel Dateioperationen, Bildschrim-Ein-/Ausgabe oder Stringverarbeitung. Bei der Bash ist jedes Modul in einer eigenen Datei untergebracht. Im Unterschied zu Programmen sind die Module nicht ausführbar und enthalten auch nicht den bei Bash-Programmen üblichen "Kommentar" #!/bin/bash in der ersten Zeile. Die einzelnen Module werden mit dem Source-Befehl in das Programm eingebunden:
#!/bin/bash source dateioperationen source einausgabe . stringverarbeitung
Der Source-Befehl kann mit einem Punkt (vierte Zeile) abgekürzt werden, diese Schreibweise findet man in der Praxis sehr oft. Trifft die Bash auf eine Source-Anweisung, wird im Speicher die gesamte Datei anstelle des Source-Befehls eingefügt und komplett abgearbeitet. Auf diese Weise ist es möglich, den Source-Befehl auch in Modulen einzusetzen, ihn also zu verschachteln.
Ein weiteres Anwendungsgebiet für source ist das Einlesen von Konfigurationsdateien. Bei SuSE-Distributionen ist die Datei /etc/rc.config eine der zentralen System-Konfigurationsdateien. Sie enthält lediglich Kommentare und Variablen-Zuweisung in Bash-Schreibweise und wird einfach mittels Source-Befehl von den jeweiligen Skript-Dateien eingelesen. In Kasten 1 finden Sie ein Beispiel zum Einlesen einer Konfigurationsdatei.
Kasten 1: Einlesen einer Konfigurationsdatei
Datei: <I>.config<I>
# Zu verwendende Sprache LANG="de_DE"
Datei: <I>dateioperationen<I>
KonfigurationPruefen ()
{
# Name der Datei erforderlich (1. Parameter)
if [ ! $# -eq 1 ]; then
return 1
# Datei muss lesbar sein
elif [ ! -r $1 ]; then
return 2
fi
return 0
}Datei: <I>konfiguration<I>
#!/bin/bash . dateioperationen KonfigurationPruefen .config && source .config echo $LANG
Im Hauptprogramm konfiguration finden Sie beide Verwendungsformen des Source-Befehls. In der zweiten Zeile wird zunächst das Modul dateioperationen geladen, in dem sich die Funktion KonfigurationPruefen befindet. Die dritte Zeile enthält eine Verkettung zweier Befehle: KonfigurationPruefen liefert wahr, also null, wenn die Datei .config lesbar ist. Nur dann wird sie mittels source eingebunden.
Es ist generell zu empfehlen, die Existenz jedes Moduls vor dem Einbinden zu überprüfen. Fehlt ein Modul, im folgenden Beispiel dateioperationen, gibt die Bash eine entsprechende Fehlermeldung aus, versucht das Skript aber dennoch laufen zu lassen. Im schlimmsten Fall führt das zu Folgefehlern durch fehlende Funktionen:
./konfiguration: dateioperationen: No such file or directory ./konfiguration: KonfigurationPruefen: command not found
Finale
Funktionen und Module sind der Schlüssel zu strukturierten, lesbaren und wiederverwendbaren Programmen. Als Nebeneffekt lässt sich damit auch eine gute Arbeitsteilung realisieren: Während sich ein Programmierer um die Dateiverwaltung kümmert, entwirft ein anderer die Benutzeroberfläche – nur auf diese Weise konnten Linux und die GNU-Programme von einer großen Gemeinde entwickelt werden. In einer endlos langen Ansammlung von Befehlen wäre längst der Überblick verloren gegangen.
Damit endet Teil sechs. Im siebten und letzten Teil des Programming Corners werden wir zum großen Finale einläuten und anhand eines Beispiel-Programms noch einmal alle Themen der vergangenen Teile ansprechen und veranschaulichen.
Glossar
globale Variablen
sind im gesamten Programm gültige Variablen, die von jeder beliebigen Stelle aus verändert werden können. Jede neue Variable ist grundsätzlich eine globale Variable, wenn sie nicht explizit zur lokalen erklärt wird.
Lokale Variablen
Lokale Variablen sind im Gegensatz zu den globalen nur in einem bestimmten Bereich oder Block gültig. Eine in einer Funktion angelegten lokale Variable kann nur innerhalb der Funktion verwendet werden, außerhalb ist sie unbekannt.



