ZIV

  Linux-Einführung

Shell-Programmierung

 

WWU


Weitere Befehle zurück vor Grafische Anwendungen

Shell-Programmierung

Die Shell ist auch eine Programmiersprache. Ein Programm (ein Shell-Skript) erzeugt man, indem man Befehle in einer ausführbaren Datei abspeichert, z.B. die Pipe zum Wörterzählen als wordcount.
Für kompliziertere Aufgaben sollte man allerdings eine Skriptsprache wie perl oder tcl verwenden.

Einfache Elemente

Das Zeichen  # bewirkt, dass der Rest der Zeile als Kommentar behandelt wird. Kommentare erhöhen die Lesbarkeit eines Programms und sollten daher reichlich verwendet werden.
Zur Steuerung von bedingten Anweisungen, Schleifen, usw. dient der Exit-Status von Programmen. Der Exitstatus einer Befehlsfolge oder eines Skripts ist der Wert, den das letzte ausgeführte Programm liefert. Will man in einem Skript selbst den Exitstatus setzen, so kann man dies mit exit wert tun.
Zwei Programme, die immer einen definierten Exitstatus erzeugen, sind true (immer 0) und false (immer 1).


Shell-Variablen und -Argumente

Variablen werden in der Shell dadurch erzeugt, dass man ihnen einen Wert zuweist. Ein Variablenname fängt mit einem Buchstaben an und darf ausserdem aus Buchstaben, Ziffern und dem Unterstrich bestehen. Damit Variablen auch in Subshells bekannt sind, müssen sie mit export Name exportiert werden.
Spezielle Variablen sind
 
  $1, $2, ...$9
  die einzelnen Argumente
  $0
  der Name des Programms
  $*
  alle Argumente
  $#
  die Anzahl der Argumente


 Der Befehl test

Mit test ausdruck bzw.  [ ausdruck ] kann man eine Bedingung prüfen und den Exit-Status true oder false erhalten.

  -f file
 file ist eine Datei
 -d file
.... ein Verzeichnis
 -r file
.... lesbar
 -w file
.... schreibbar
 -x file
.... ausführbar
 -s file
.... nicht leer
 -z string
 Zeichenkette ist leer
 -n string
.... nicht leer
 string1 = string2
 Zeichenketten sind gleich
 string2 != string2
.... ungleich
 n1 -eq n2
 Zahlen sind gleich
 n1 -ne n2
.... ungleich
 n1 -lt n2 (-le, -gt, -ge)
 Zahl 1 ist kleiner (kleiner oder gleich, grösser, grösser oder gleich) Zahl 2
 ( ausdruck )
 Klammerung von Teilausdrücken
 ! ausdruck
 Negation
 -a
 AND
 -o
 OR







Kommando-Strukturen

Die bedingte Anweisung

if bedingung
then
        kommandos1
else
        kommandos2
fi

führt die Anweisung(en) bedingung aus. Falls der Exit-Status true ist, werden die Befehle nach then, sonst die nach else ausgeführt. Der else-Teil kann auch fehlen.
In der erweiterten Form

if
bedingung1
then
        kommandos1
elif bedingung2
then
        kommandos2
else
        kommandos3
fi    

wird, falls die erste Bedingung false ist, die zweite Bedingung überprüft und entsprechend verzweigt. Es kann auch mehr als ein elif vorkommen.

Beispiel:

Das folgende Skript legt eine Datei .tstlock an, falls diese noch nicht existiert und gibt sie nach $1 Sekunden wieder frei. Falls .tstlock schon existiert, gibt das Skript eine Fehlermeldung aus und endet. Eine solche Konstruktion dient dazu, mehrfache Zugriffe auf z.B. eine Mailbox zu verhindern.

#
# getlock sec
#
LOCKFILE=$HOME/.tstlock

if [ $# -ne 1 ]
then
     echo "Aufruf: $0 sekunden"
     exit -1
fi

if [ -f $LOCKFILE ]
then
     echo "$LOCKFILE existiert schon"
     exit 1
fi

> $LOCKFILE                         # Lock erzeugen
sleep $1
rm $LOCKFILE                        # und wieder löschen
 

Die Kommandos in einer while-Schleife 

while bedingung
do
        kommandos
done

werden ausgeführt, solange die Bedingung true ist.
 

Beispiel

In Abänderung des vorigen Beispiels wird jetzt gewartet, bis das Lockfile angelegt werden kann:
#
# getlock sec
#
LOCKFILE=$HOME/.tstlock
if [ $# -ne 1 ]
then
    echo "Aufruf: $0 sekunden"
    exit -1
fi
if [ -f $LOCKFILE ]
then
    echo -n "Warten auf $LOCKFILE "
    while [ -f $LOCKFILE ]
    do
        echo -n ".."
        sleep 2
    done
    echo " fertig"
fi

> $LOCKFILE             # Lock erzeugen
sleep $1
rm $LOCKFILE            # und wieder löschen  
 


Im Gegensatz zur while-Schleife werden in der until-Schleife

until  bedingung
do
        kommandos
done

die Befehle ausgeführt,  solange die Bedingung false ist.

Beispiel

Das folgende Skript führt den sleep-Befehl solange aus, bis  sich der als Argument angegebene Benutzer eingeloggt hat.
 
until who | grep $1     # Exitstatus von grep

do
    sleep 10
done
echo "$1 ist jetzt da"  

 

 Eine for-Schleife erhält eine Liste von Werten und führt die Kommandos mit jedem dieser Werte in der Laufvariablen
aus. 

for  var  in liste
do
        kommandos
done
 

  Beispiel

Die Argumente werden einzeln ausgegeben:

for argument in $*        
do
    echo $argument
done
   

Schleifen können vorzeitig abgebrochen werden:

Beispiel

Die for-Schleife gibt nur 1 und 3 aus:

for b in 1 2 3 4 5
do
    if [ $b -eq 2 ]
    then
        continue
    fi
    if [ $b -eq 4 ]
    then
        break
    fi

    echo $b
done

 
 
Die Variable einer case-Anweisung

case  var   in
muster1)     kommandos1 ;;
muster2)     kommandos2 ;;
....
esac

wird der Reihe nach mit  den Mustern verglichen und nur die zum ersten passenden Muster gehörenden Befehle werden ausgeführt. Die Muster haben die gleiche Syntax wird die Dateinamen-Expansion. Alternativen können durch | angegeben werden. Das Muster * trifft immer zu und dient am Ende der Anweisung dazu, Befehle auszuführen, wenn keins der anderen Muster passte.

Beispiel

Das Programm cal erlaubt zur Angabe des Monats nur eine Zahl. Dieser Mangel kann mit dem folgenden Skript behoben werden:

#
# Schnittstelle zu cal, erlaubt cal jan 1993

#
case $# in
0) m=""; y="" ;;
1) m=""; y=$1 ;;
*) m=$1; y=$2
esac

case $m in
Jan*|jan*) m=1 ;;
Feb*|feb*) m=2 ;;
Mar*|mar*) m=3 ;;
Apr*|apr*) m=4 ;;
Mai*|mai*) m=5 ;;
Jun*|jun*) m=6 ;;
Jul*|jul*) m=7 ;;
Aug*|aug*) m=8 ;;
Sep*|sep*) m=9 ;;
Okt*|okt*) m=10 ;;
Nov*|nov*) m=11 ;;
Dez*|dez*) m=12 ;;
*)        ;; # alles andere, z.B eine Zahl   
esac

/usr/bin/cal $m $y
 
 

Benutzereingaben

Der Befehl

read var1 [var2 ...]

liest eine Zeile von der Standard-Eingabe und weist die
einzelnen Worte den Variablen zu.
Wenn mehr Worte als Variablen vorhanden sind,  erhält die letzte Variable den Rest der Zeile;
wenn die Eingabe zu kurz ist, bleiben die letzten Variablen leer.

Übungen

  1. Schreiben Sie ein Programm, das für eine als Argument angegebene Datei feststellt, ob es sich um eine gewöhnliche Datei, ein Verzeichnis oder etwas anderes handelt. Falls es sich um eine gewöhnliche Datei handelt, soll ausserdem geprüft werden, ob sie ausführbar ist.
  2. Ändern Sie das Programm so, dass es auch mehrere Dateien überprüft.
  3. Schreiben Sie ein Programm, das solange interaktiv Zeilen einliest, bis es durch Eingabe von 'stop' beendet wird. Die eingelesenen Daten sollen in Grossbuchstaben übersetzt werden.
  4.  Erweitern Sie das Programm aus der vorigen Aufgabe so, dass die Eingabeaufforderung optional unterdrückt werden kann.

 
 


 
 
 


Vorlesungsübersicht zurück vor Grafische Anwendungen

Zentrum für Informationsverarbeitung / © Mathias Grote / Letzte Änderung:  2. Oktober 2007