Unterabschnitte


Variablen, Parameter

Variablen heißen in der Shell nicht Variablen, sondern Shellparameter. Da aber in allen anderen Sprachen Variablen halt Variablen heißen, und Parameter die Dinger sind, die man an ein Programm oder an eine Funktion übergibt, werde ich Variablen auch weiterhin so nennen.

Variablen werden in der Shell als Zeichenketten (Strings) gespeichert. Es gibt einfach keine numerischen Variablen. Strukturen (struct, class), oder so etwas wie union oder Record sowieso nicht.

Um eine Variable zu verwenden, schreibt man ein Dollarzeichen $, gefolgt vom Variablennamen. Den Wert der Variablen EGON kann verwenden, indem $EGON schreibt.

Wenn direkt an den Variablennamen weiterer Text anschließt, kann die Shell natürlich nicht erkennen, wo der Name nun enden soll. Angenommen, man hat die Variable BASIS auf den Wert 10 gesetzt, und möchte jetzt mit dem Ausdruck $BASISE3 den String 10E3 erzeugen, dann wird das nicht klappen, weil die Shell nicht nach dem Namen BASIS sucht, sondern nur nach BASISE, Als Lösung bietet es sich dann an, den gewünschten Variablennamen in geschweifte Klammern zu setzen: ${BASIS}E3 liefert tatsächlich 10E3.

Wenn man eine Variable NAME verwendet, die nicht definiert ist, dann liefert $NAME einen leeren String. Insofern sieht man meistens keinen Unterschied zwischen einer Variablen, die gar nicht gesetzt ist, und einer Variablen, der ein leerer String zugewiesen ist. Manchmal ist der Unterschied aber von Belang, siehe Vordefinierte und spezielle Variablen, shift, set. Eine gänzlich undefinierte Variable liefert nämlich bei ihrer Verwendung einen Nullwert, der sich in Ausdrücken manchmal anders verhält als ein leerer String. Will man eine bereits vorhandene Variable wirklich löschen, so daß sie den Nullwert liefert, dann kann man das mit unset machen; Beispiel:
klaus@aw35:~ > unset NAME
Wenn die Variable vorher gar nicht existiert hatte, schadet der Befehl auch nichts.



Die Parameter eines Skripts lassen sich mit dem (internen) Kommando getopts leichter auswerten als zu Fuß. Das setzt aber voraus, daß die Optionen Unix-üblich vor weiteren Argumenten kommen, und nur aus einem Bindestrich und einem weiteren Buchstaben bestehen (wie beispielsweise bei einem Druckaufruf lpr -c -P lp2 -s datei1 datei2).

Mit getopts lassen sich Parameter verarbeiten, die keine Argumente haben (-c und -s im lpr-Beispiel), oder genau ein Argument haben (-P im lpr-Beispiel). Die restlichen Argumente (hier datei1 und datei2) müssen nach den Optionen kommen, und werden von getopts nicht verarbeitet.

getopts wird mit (mindestens) zwei Argumenten aufgerufen. Das erste Argument ist ein String, in dem die zu erkennenden Optionen angegeben sind. Eine Option, die ein zusätzliches Argument erhält, kennzeichnet man durch einen nachfolgenden Doppelpunkt (:). Um die lpr-Optionen für das obige Beispiel zu erkennen, müßte man also den String "P:cs" angeben.

Das zweite Argument ist der Name einer Variablen, in der die erkannte Option gespeichert wird (ohne Bindestrich).

getopts liefert mit jedem Aufruf eine weitere Option aus der Parameterliste, und gibt true (also 0) zurück, wenn eine Option gefunden wurde, oder false, wenn keine Option mehr gefunden werden kann.

Wenn eine der Optionen ein weiteres Argument hat (im String mit dem Doppelpunkt (:) markiert), dann wird dieses Argument in der Variablen OPTARG hinterlegt.

Die Parameterliste selbst wird nicht verändert.

Beispiel 4   Mit dem Skript:
#!/bin/sh

# Die Optionen -i, -j, -k und -l sollen erkannt werden,
# wobei für -k ein Argument angegeben werden muß:
while getopts "ijk:l" option
do
        case $option in
        i)   echo Die Option i
             ;;
        j)   echo die Option j
             ;;
        k)   echo die Option k mit Argument $OPTARG
             ;;        
        l)   echo die Option l
             ;;
        \?)  echo falsche Argumente
             ;;
        *)   echo sollte nicht vorkommen
             ;;
        esac
done
erhält man beim Aufruf mit den Optionen -i -k blabla -l folgende Ausgabe:
Die Option i
die Option k mit Argument blabla
die Option l

getopts muß sich von einem Aufruf zum nächsten merken, wie weit es die Argumente schon ausgewertet hat. Dazu verwendet es die Variable OPTIND. Diese wird beim Starten eines Skripts automatisch auf 1 gesetzt, und von getopts bei jedem Aufruf weiter gezählt. Dies kann man nutzen:

  1. um nach dem letzten getopts-Aufruf an weitere Argumente des Shellprogramms heran zu kommen (im lpr-Beispiel die Dateinamen datei1 und datei2)
  2. wenn man die Optionen ein zweites Mal ausgewertet haben will, setzt man einfach OPTIND selbst wieder auf 1, und kann dann wieder in einer Schleife getopts aufrufen, bis es false liefert.

Beispiel 5   Wenn man also an weitere Parameter (nach den Optionen) heran kommen möchte, kann man das Skript so erweitern:
#!/bin/sh

# Die Optionen -i, -j, -k und -l sollen erkannt werden,
# wobei für -k ein Argument angegeben werden muß:
while getopts "ijk:l" option
do
        case $option in
        i)   echo Die Option i
             ;;
        j)   echo die Option j
             ;;
        k)   echo die Option k mit Argument $OPTARG
             ;;        
        l)   echo die Option l
             ;;
        \?)  echo falsche Argumente
             ;;
        *)   echo sollte nicht vorkommen
             ;;
        esac
done

# OPTIND hat den Wert (Anzahl der ausgewerteten Parameter)+1.
# Diese Argumente brauchen wir schon nicht mehr, und verschieben
# deshalb die Argumente um $OPTIND-1 nach unten:
shift `expr $OPTIND - 1`

# Anzeige der restlichen Parameter:
echo $*

Bei einem Aufruf mit den Parametern -k keinegnade -l blabla abc erhält man die Ausgabe:
die Option k mit Argument keinegnade
die Option l
blabla abc
Siehe dazu auch Numerik light mit expr, while-Schleife, Vordefinierte und spezielle Variablen, shift, set, und case.


Namen von Variablen

Die Namen von Variablen dürfen aus den 26 kleinen (a-z) Buchstaben, den 26 großen (A-Z) Buchstaben, den 10 dezimalen Ziffern (0-9), und dem Unterstrich _ (under score) gebildet werden.

Groß- und Kleinschreibung wird unterschieden.

Wie in vielen anderen Sprachen auch darf ein Name nicht mit einer Ziffer beginnen.


Setzen von Variablen, Exportieren

Bestehende Variablen kann man überschreiben, oder nicht bestehende neu anlegen, indem man ihnen einfach einen Wert zuweist:
klaus@aw35:~ > EGON=Waldschrat
klaus@aw35:~ > ZAHL=35
klaus@aw35:~ > PI=3.14159265

So definierte Variablen werden an Kind-Shells erstmal nicht weiter vererbt (im Gegensatz zu PATH beispielsweise).

Dazu muß man der Shell mit export sagen, daß man die Variablen vererbt haben möchte.

Beispiel 6   Weitervererben einer Variable an Kind-Shells
Setzen einer Variable und testweise Ausgabe:
klaus@aw35:~ > FUENF=5
klaus@aw35:~ > echo $FUENF
5
Aufruf einer Kind-Shell:
klaus@aw35:~ > bash
Kennt diese Shell die Variable?
klaus@aw35:~ > echo $FUENF

Offenbar nicht. Kind-Shell wieder beenden.
klaus@aw35:~ > exit
Jetzt sind wir wieder in der ursprünglichen Shell.
Variable exportieren:
klaus@aw35:~ > export FUENF
Nochmal eine Kind-Shell aufrufen:
klaus@aw35:~ > bash
Kennt diese Shell die Variable?
klaus@aw35:~ > echo $FUENF
5
Offenbar ja.
klaus@aw35:~ > exit
klaus@aw35:~ >

Das Setzen einer Variablen und das Exportieren kann man auch zusammenfassen:
klaus@aw35:~ > EGON=Waldschrat
klaus@aw35:~ > ZAHL=35
klaus@aw35:~ > PI=3.14159265
klaus@aw35:~ > export EGON ZAHL PI
ist gleichbedeutend mit:
klaus@aw35:~ > export EGON=Waldschrat
klaus@aw35:~ > export ZAHL=35
klaus@aw35:~ > export PI=3.14159265

AnyWare@Wachtler.de