|
|
(11 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) |
Zeile 1: |
Zeile 1: |
| '''Bash/Kontrollstrukturen''' - Verzweigungen, Schleifen, Fallunterscheidungen
| |
|
| |
| == Beschreibung ==
| |
| Ablauf eines Linux-Shell-Skripts steuern
| |
|
| |
| == Bedingungen ==
| |
| === Bedingungen testen ===
| |
| siehe [[test]]
| |
|
| |
| === if - then - else ===
| |
| Als Bedingung kann nicht nur der test-Befehl, sondern eine beliebige Folge von Kommandos verwendet werden
| |
| * Jedes Kommando liefert einen Errorcode zurück, der bei erfolgreicher Ausführung gleich Null (true) und bei einem Fehler oder Abbruch ungleich Null (false) ist
| |
|
| |
| ; Testen einer Bedingung mit der if-Anweisung
| |
| Jede Anweisung muss entweder in einer eigenen Zeile stehen oder durch einen Strichpunkt von den anderen Anweisungen getrennt werden
| |
| * Trotzdem verhält sich eine bedingte Anweisung - oder die Schleifenkonstrukte, die weiter unten behandelt werden - wie eine einzige Anweisung
| |
| * Man kann dies ausprobieren, indem man eine if- oder while-Anweisung interaktiv eingibt. Solange nicht 'fi' bzw. 'done' eingetippt wurde, erhält man den PS2-Prompt ('>')
| |
|
| |
| Die if-Anweisung in der Shell-Programmierung macht das gleiche wie in allen anderen Programmiersprachen, sie testet eine Bedingung auf Wahrheit und macht davon den weiteren Ablauf des Programms abhängig
| |
|
| |
| ; Syntax
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| if Bedingung1
| |
| then Befehle1
| |
| [ elif Bedingung2
| |
| then Befehle2 ]
| |
| ..
| |
| [ else Befehle3 ]
| |
| fi
| |
| </syntaxhighlight>
| |
|
| |
| * Wenn die Bedingung1 erfüllt ist, werden die Befehle1 ausgeführt
| |
| ** andernfalls, wenn die Bedingung2 erfüllt ist, werden die Befehle2 ausgeführt
| |
| * Trifft keine Bedingung zu, sollen die Befehle3 ausgeführt werden
| |
| * Bedingungen werden normalerweise mit dem Befehl test formuliert
| |
| * Es kann aber auch der Rückgabewert jedes anderen Kommandos ausgewertet werden
| |
| * Für Bedingungen, die auf jeden Fall zutreffen sollen steht der Null-Befehl (:) zur Verfügung
| |
|
| |
| ; Beispiele
| |
| Man achte auf die Positionierung der Semikoli
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| #!/bin/sh
| |
| # Füge eine 0 vor Zahlen kleiner 10 ein
| |
|
| |
| counter=0
| |
| if [counter -lt 10 ]; then
| |
| number=0$counter; else number=$counter; fi
| |
| </syntaxhighlight>
| |
|
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| #!/bin/bash
| |
| # Erstelle ein Verzeichnis, wenn es noch nicht existiert
| |
| dir=daten
| |
| if [ ! -edir ]; then
| |
| mkdirdir; fi # mkdir: Verzeichnis erstellen
| |
| </syntaxhighlight>
| |
|
| |
| ==== einseitiges if ====
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| if kommandoliste
| |
| then
| |
| kommandos
| |
| fi
| |
| </syntaxhighlight>
| |
|
| |
| ==== zweiseitiges if ====
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| if kommandoliste
| |
| then
| |
| kommandos
| |
| else
| |
| kommandos
| |
| fi
| |
| </syntaxhighlight>
| |
|
| |
| ==== Mehrstufiges if ====
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| if kommandoliste1
| |
| then
| |
| kommandos
| |
| elif kommandoliste2
| |
| then
| |
| kommandos
| |
| elif ..
| |
| ..
| |
| fi
| |
| </syntaxhighlight>
| |
|
| |
| === Beispiele ===
| |
| Es soll eine Meldung ausgegeben werden, falls mehr als 5 Benutzer eingeloggt sind
| |
| <syntaxhighlight lang="bash" highlight="" line="" copy="">
| |
| USERS=`who | wc -l` # Zeilen der who-Ausgabe zählen
| |
| if test USERS -gt 5
| |
| then
| |
| echo "Mehr als 5 Benutzer am Geraet"
| |
| fi
| |
| </syntaxhighlight>
| |
|
| |
| Kürzere Variante
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| if [(who | wc -l) -gt 5 ] ; then
| |
| echo "Mehr als 5 Benutzer am Geraet"
| |
| fi
| |
| </syntaxhighlight>
| |
|
| |
| Man sollte bei der Entwicklung von Skripts aber ruhig mit der Langfassung beginnen und sich erst der Kurzfassung zuwenden, wenn man mehr Übung hat und die Langfassungen auf Anhieb funktionieren
| |
|
| |
| Ein weiteres Beispiel zeigt eine Fehlerprüfung
| |
| <syntaxhighlight lang="bash" highlight="" line="" copy="">
| |
| if test # -eq 0
| |
| then
| |
| echo "usage: sortiere filename" >&2
| |
| else
| |
| sort +1 -21 | lp
| |
| fi
| |
| </syntaxhighlight>
| |
|
| |
| ; Beispiel
| |
| Zeigt eine mehr oder weniger intelligente Anzeige für Dateien und Verzeichnisse.
| |
|
| |
| 'show' zeigt bei Dateien den Inhalt mit 'less' an und Verzeichnisse werden mit 'ls' präsentiert
| |
| * Fehlt der Parameter, wird interaktiv nachgefragt
| |
| <syntaxhighlight lang="bash" highlight="" line="" copy="">
| |
| if [# -eq 0 ] # falls keine Angabe
| |
| then # interaktiv erfragen
| |
| echo -n "Bitte Namen eingeben: "
| |
| read DATEI
| |
| else
| |
| DATEI=$1
| |
| fi
| |
| if [ -f DATEI ] # wenn normale Datei
| |
| then # dann ausgeben
| |
| lessDATEI
| |
| elif [ -d DATEI ] # wenn aber Verzeichnis
| |
| then # dann Dateien zeigen
| |
| ls -CF DATEI
| |
| else # sonst Fehlermeldung
| |
| echo "cannot showDATEI"
| |
| fi
| |
| </syntaxhighlight>
| |
|
| |
| ; Beispiel
| |
| Hängt eine Datei an eine andere Datei an; vorher erfolgt eine Prüfung der Zugriffsberechtigungen
| |
|
| |
| append Datei1 Datei2
| |
|
| |
| <syntaxhighlight lang="bash" highlight="" line="" copy="">
| |
| if [ -r $1 -a -w $2 ]
| |
| then
| |
| cat $1 >> $2
| |
| else
| |
| echo "cannot append"
| |
| fi
| |
| </syntaxhighlight>
| |
|
| |
| Beim Vergleich von Zeichenketten sollten möglichst die Anführungszeichen (" ... ") verwendet werden, da sonst bei der Ersetzung durch die Shell unvollständige Test-Kommandos entstehen können
| |
|
| |
| ; Beispiel
| |
| <syntaxhighlight lang="bash" highlight="" line="" copy="">
| |
| if [ ! -n $1 ] ; then
| |
| echo "Kein Parameter"
| |
| fi
| |
| </syntaxhighlight>
| |
|
| |
| Ist 1 wirklich nicht angegeben, wird das Kommando reduziert zu
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| if [ ! -n ] ; then ...
| |
| </syntaxhighlight>
| |
|
| |
| Es ist also unvollständig und es erfolgt eine Fehlermeldung. Dagegen liefert
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| if [ ! -n "$1" ] ; then
| |
| echo "Kein Parameter"
| |
| fi
| |
| </syntaxhighlight>
| |
|
| |
| bei fehlendem Parameter den korrekten Befehl
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| if [ ! -n "" ]
| |
| </syntaxhighlight>
| |
|
| |
| Bei fehlenden Anführungszeichen werden auch führende Leerzeichen der Variablenwerte oder Parameter eliminiert
| |
|
| |
| ; Weiteres Beispiel
| |
| Es kommt vor, dass eine Userid wechselt oder die Gruppenzugehörigkeit von Dateien geändert werden muss. In solchen Fällen helfen die beiden folgenden Skripte
| |
| <syntaxhighlight lang="bash" highlight="" line="" copy="">#!/bin/sh
| |
| # Change user-id
| |
| #
| |
| if [# -ne 2 ] ; then
| |
| echo "usage `basename0` <old id> <new id>"
| |
| exit
| |
| fi
| |
| find ~ -user1 -exec chown2 {} ";"
| |
| #!/bin/sh
| |
| # Change group-id
| |
| #
| |
| if [# -ne 2 ] ; then
| |
| echo "usage `basename0` <old id> <new id>"
| |
| exit
| |
| fi
| |
| find / -group1 -exec chgrp2 {} ";"</syntaxhighlight>
| |
|
| |
| == Fallunterscheidung ==
| |
| ; case
| |
| Auch die case-Anweisung ist vergleichbar in vielen anderen Sprachen vorhanden
| |
| * Sie dient, ähnlich wie die if-Anweisung, zur Fallunterscheidung. Allerdings wird hier nicht nur zwischen zwei Fällen unterschieden (Entweder / Oder), sondern es sind mehrere Fälle möglich
| |
| * Man kann die case-Anweisung auch durch eine geschachtelte if-Anweisung völlig umgehen, allerdings ist sie ein elegantes Mittel um den Code lesbar zu halten
| |
|
| |
| Die Syntax der case-Anweisung lautet wie folgt
| |
| <syntaxhighlight lang="bash" highlight="" line>
| |
| case Wert in
| |
| Muster1) Befehle1;;
| |
| Muster2) Befehle2;;
| |
| ..
| |
| esac
| |
| </syntaxhighlight>
| |
|
| |
| Wenn der Wert mit dem Muster1 übereinstimmt, wird die entsprechende Befehlsgruppe (Befehle1) ausgeführt, bei Übereinstimmung mit Muster2 werden die Kommandos der zweiten Befehlsgruppe (Befehle2) ausgeführt, und weitere
| |
| * Der letzte Befehl in jeder Gruppe muss mit ;; gekennzeichnet werden
| |
| * Das bedeutet für die Shell soviel wie springe zum nächsten esac, so dass die anderen Bedingungen nicht mehr überprüft werden
| |
| * In den Mustern sind die gleichen Meta-Zeichen erlaubt wie bei der Auswahl von Dateinamen
| |
| * Wenn in einer Zeile mehrere Muster angegeben werden sollen, müssen sie durch ein Pipezeichen (|, logisches ODER) getrennt werden
| |
|
| |
| ; Beispiele
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| #!/bin/sh
| |
| # Mit dem ersten Argument in der Befehlszeile
| |
| # wird die entsprechende Aktion festgelegt
| |
|
| |
| case 1 in # nimmt das erste Argument
| |
| Ja|Nein) response=1;;
| |
| *) echo "Unbekannte Option"; exit 1;;
| |
| esac
| |
| </syntaxhighlight>
| |
|
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| #!/bin/sh
| |
| # Lies die Zeilen von der Standardeingabe, bis eine
| |
| # Zeile mit einem einzelnen Punkt eingegeben wird
| |
| while : # Null-Befehl
| |
| do
| |
| echo -e "Zum Beenden . eingeben ==> \c"
| |
| read line # read: Zeile von StdIn einlesen
| |
| case "$line" in
| |
| .) echo "Ausgefuehrt"
| |
| break;;
| |
| *) echo "$line" >>./message ;;
| |
| esac
| |
| done
| |
| </syntaxhighlight>
| |
|
| |
| ; case-Anweisung
| |
| Diese Anweisung erlaubt eine Mehrfachauswahl. Sie wird auch gerne deshalb verwendet, weil sie Muster mit Jokerzeichen und mehrere Muster für eine Auswahl erlauben
| |
| case selector in
| |
| <syntaxhighlight lang="bash" highlight="" line>
| |
| Muster-1) Kommandofolge 1 ;;
| |
| Muster-2) Kommandofolge 2 ;;
| |
| ...
| |
|
| |
| Muster-n) Kommandofolge n ;;
| |
| esac
| |
| </syntaxhighlight>
| |
|
| |
| Die Variable <tt>selector</tt> (String) wird der Reihe nach mit den Mustern "Muster-1" bis "Muster-n" verglichen. Bei Gleichheit wird die nachfolgende Kommandofolge ausgeführt und dann nach der case-Anweisung (also hinter dem <tt>esac</tt>) fortgefahren. * In den Mustern sind Metazeichen (*, ?, []) erlaubt, im Selektor dagegen nicht
| |
| * Das Muster * deckt sich mit jedem Selektor --> default-Ausgang. muss als letztes Muster in der case-Konstruktion stehen
| |
| * Vor der Klammer können mehrere Muster, getrennt durch <tt>| </tt>stehen
| |
|
| |
| ; Das Zeichen <tt>| </tt>bildet eine Oder-Bedingung
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| case selector in
| |
| Muster1) Kommandofolge1 ;;
| |
| Muster2 | Muster3) Kommandofolge2 ;;
| |
| *) Kommandofolge3 ;;
| |
| esac
| |
| </syntaxhighlight>
| |
|
| |
| ; Beispiel 1
| |
| Automatische Bearbeitung von Quell- und Objekt-Dateien. Der Aufruf erfolgt mit 'compile Datei'
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| case1 in
| |
| *.s) as1 ;; # Assembler aufrufen
| |
| *.c) cc -c1 ;; # C-Compiler aufrufen
| |
| *.o) cc1 -o prog ;; # C-Compiler als Linker
| |
| *) echo "invalid parameter:1";;
| |
| esac
| |
| </syntaxhighlight>
| |
|
| |
| ; Beispiel 2
| |
| Menü mit interaktiver Eingabe
| |
| <syntaxhighlight lang="bash" highlight="" line="" copy="">
| |
| while : # Endlosschleife
| |
| do
| |
| tput clear # Schirm löschen und Menütext ausgeben
| |
| echo " +---------------------------------+"
| |
| echo " | 0 --> Ende |"
| |
| echo " | 1 --> Datum und Uhrzeit |"
| |
| echo " | 2 --> aktuelles Verzeichnis |"
| |
| echo " | 3 --> Inhaltsverzeichnis |"
| |
| echo " | 4 --> Mail |"
| |
| echo "+----------------------------------+"
| |
| echo "Eingabe: \c" # kein Zeilenvorschub
| |
| read ANTW
| |
| case ANTW in
| |
| 0) kill -9 0 ;; # und tschuess
| |
| 1) date ;;
| |
| 2) pwd ;;
| |
| 3) ls -CF ;;
| |
| 4) elm ;;
| |
| *) echo "Falsche Eingabe!" ;;
| |
| esac
| |
| done
| |
| </syntaxhighlight>
| |
|
| |
| == Schleifen ==
| |
| ; for-Anweisung
| |
| Diese Schleifenanweisung hat zwei Ausprägungen
| |
| * mit einer Liste der zu bearbeitenden Elemente
| |
| * mit den Kommandozeilenparametern
| |
|
| |
| Dieses Konstrukt ähnelt nur auf den ersten Blick seinen Pendants aus anderen Programmiersprachen
| |
| * In anderen Sprachen wird die for-Schleife meistens dazu benutzt, eine Zählvariable über einen bestimmten Wertebereich iterieren zu lassen (for i = 1 to 100...next)
| |
| * In der Shell dagegen wird die Laufvariable nicht mit aufeinander folgenden Zahlen belegt, sondern mit einzelnen Werten aus einer anzugebenden Liste
| |
| * Wenn man eine Laufvariable benötigt, muss man dazu die while-Schleife einsetzen
| |
|
| |
| Die Syntax der for-Schleife lautet wie folgt
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| for x [ in Liste ]
| |
| do
| |
|
| |
| Befehle
| |
|
| |
| done
| |
| </syntaxhighlight>
| |
|
| |
| Die Befehle werden ausgeführt, wobei der Variablen x nacheinander die Werte aus der Liste zugewiesen werden
| |
| * Wie man sieht, ist die Angabe der Liste optional, wenn sie nicht angegeben wird, nimmt x der Reihe nach alle Werte aus@ (in dieser vordefinierten Variablen liegen die Aufrufparameter) an
| |
| * Wenn die Ausführung eines Schleifendurchlaufs bzw. der ganzen Schleife abgebrochen werden soll, müssen die Kommandos continue bzw. break benutzt werden
| |
|
| |
| === for-Schleife mit Liste ===
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| for selector in liste
| |
| do
| |
| Kommandofolge
| |
| done
| |
| </syntaxhighlight>
| |
|
| |
| Die Selektor-Variable wird nacheinander durch die Elemente der Liste ersetzt und die Schleife mit der Selektor-Variablen ausgeführt
| |
|
| |
| ; Beispiele
| |
| <syntaxhighlight lang="bash" highlight="" line="" copy="">
| |
| for X in hans heinz karl luise do echo X done
| |
| </syntaxhighlight>
| |
|
| |
| Ausgabe
| |
| <syntaxhighlight lang="bash" highlight="" line>
| |
| hans
| |
| heinz
| |
| karl
| |
| luise
| |
| </syntaxhighlight>
| |
|
| |
| <syntaxhighlight lang="bash" highlight="" line="" copy="">
| |
| for FILE in *.txt # drucke alle Textdateien
| |
| do # im aktuellen Verzeichnis
| |
| lpr FILE
| |
| done
| |
| for XX in VAR # geht auch mit
| |
| do
| |
| echo XX
| |
| done
| |
| </syntaxhighlight>
| |
|
| |
| Durchsuche Kapitel zur Erstellung einer Wortliste (wie fgrep -f)
| |
| <syntaxhighlight lang="bash" highlight="" line="" copy="">
| |
| for item in (cat program_list) # cat: Datei ausgeben
| |
| do
| |
| echo "Pruefung der Kapitel auf"
| |
| echo "Referenzen zum Programmitem ..."
| |
| grep -c "$item.[co]" chap* # grep: nach Muster suchen
| |
| done
| |
| </syntaxhighlight>
| |
|
| |
| === for-Schleife mit Parametern ===
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| for selector
| |
| do
| |
| Kommandofolge
| |
| done
| |
| </syntaxhighlight>
| |
|
| |
| Die Selektor-Variable wird nacheinander durch die Parameter1 bisn ersetzt und mit diesen Werten die Schleife durchlaufen. Es gibt also# Schleifendurchläufe
| |
|
| |
| ; Beispiel
| |
| Die Prozedur 'makebak' erzeugt für die in der Parameterliste angegebenen Dateien eine .bak-Datei
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| for FF
| |
| do
| |
| cpFF{FF}.bak
| |
| done
| |
| #!/bin/sh
| |
| # Seitenweises Formatieren der Dateien, die auf der
| |
| # Befehlszeile angegeben wurden, und speichern des
| |
| # jeweiligen Ergebnisses
| |
|
| |
| for file do
| |
| prfile >file.tmp # pr: Formatiert Textdateien
| |
| done
| |
| # Ermittle einen Ein-Wort-Titel aus jeder Datei und
| |
| # verwende ihn als neuen Dateinamen
| |
|
| |
| for file do
| |
| name=`sed -n 's/NAME: //p'file`
| |
| # sed: Skriptsprache zur Textformatierung
| |
| mvfilename
| |
| # mv: Datei verschieben bzw. umbenennen
| |
| done
| |
| </syntaxhighlight>
| |
|
| |
| === while ===
| |
| Die while-Schleife ist wieder ein Konstrukt, das einem aus vielen anderen Sprachen bekannt ist
| |
|
| |
| Die kopfgesteuerte Schleife. Die Syntax der while-Schleife lautet wie folgt
| |
|
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| while Bedingung
| |
| do
| |
|
| |
| Befehle
| |
| done
| |
| </syntaxhighlight>
| |
|
| |
| Die Befehle werden so lange ausgeführt, wie die Bedingung erfüllt ist
| |
|
| |
| Dabei wird die Bedingung vor der Ausführung der Befehle überprüft. Die Bedingung wird dabei üblicherweise, genau wie bei der if-Anweisung, mit dem Befehl test formuliert
| |
|
| |
| Wenn die Ausführung eines Schleifendurchlaufs bzw. der ganzen Schleife abgebrochen werden soll, müssen die Kommandos continue bzw. break benutzt werden
| |
|
| |
| ; Beispiele
| |
| <syntaxhighlight lang="bash" highlight="" line="" copy="">
| |
|
| |
| #!/bin/sh
| |
| # Zeilenweise Ausgabe aller Aufrufparameter
| |
|
| |
| while [ -n "$1"]; do
| |
|
| |
| echo 1
| |
| shift # mit shift werden die Parameter nach
| |
| # Links geshiftet (aus2 wird1)
| |
| done
| |
| </syntaxhighlight>
| |
|
| |
|
| |
| ; Zählschleife
| |
| In anderen Sprachen kann man mit der for-Schleife eine Zählvariable über einen bestimmten Wertebereich iterieren lassen (for i = 1 to 100...next)
| |
|
| |
| Da das mit der for-Schleife der Shell nicht geht, ersetzt man die Funktion durch geschickte Anwendung der while-Schleife
| |
| <syntaxhighlight lang="bash" highlight="" line="" copy="">
| |
| #!/bin/sh
| |
| # Ausgabe der Zahlen von 1 bis 100
| |
| i=1
| |
| while [ i -le 100 ]
| |
| do
| |
| echoi
| |
| i=`expri + 1`
| |
| done
| |
| </syntaxhighlight>
| |
|
| |
| ; Weitere Beispiele
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| #!/bin/sh
| |
|
| |
| while who | grep "^root "
| |
| do sleep 30
| |
|
| |
| done
| |
|
| |
| echo Die Katze ist aus dem Haus, Zeit, dass die Mäuse tanzen!
| |
| </syntaxhighlight>
| |
|
| |
| ; Ergebniswert eines Kommandos
| |
| Als Bedingung kann nicht nur eine "klassische" Bedingung (<tt>test</tt> oder <tt>[ ]</tt>) sondern auch der Ergebniswert eines Kommandos oder einer Kommandofolge verwendet werden
| |
|
| |
| <syntaxhighlight lang="bash" highlight="" line="" copy="">
| |
| while Bedingung
| |
| do
| |
| Kommandofolge
| |
| done</syntaxhighlight>
| |
|
| |
| Solange der Bedingungsausdruck den Wert 'true' liefert, wird die Schleife ausgeführt
| |
|
| |
| ; Warten auf eine Datei (beispielsweise vom Hintergrundprozess)
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| while [ ! -f foo ]
| |
| do
| |
| sleep 10 # Wichtig damit die Prozesslast nicht zu hoch wird
| |
| done
| |
|
| |
| ; Pausenfüller für das Terminal Abbruch mit DEL-Taste
| |
| while
| |
| do
| |
| tput clear # BS löschen
| |
| echo -e "\n\n\n\n\n" # 5 Leerzeilen
| |
| banner(date '+ %T ') # Uhrzeit groß
| |
| sleep 10 # 10s Pause
| |
| done
| |
| </syntaxhighlight>
| |
|
| |
| ; Umbenennen von Dateien durch Anhängen eines Suffix
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| # Aufruf change suffix datei(en)
| |
| if [# -lt 2 ] ; then
| |
| echo "Usage: `basename0` suffix file(s)"
| |
| else
| |
| SUFF=$1 # Suffix speichern
| |
| shift
| |
| while [# -ne 0 ] # solange Parameter da sind
| |
| do
| |
| mv1{1}.$SUFF # umbenennen
| |
| shift
| |
| done
| |
| fi
| |
| </syntaxhighlight>
| |
|
| |
| ; Umbenennen von Dateien durch Anhängen eines Suffix Variante 2 mit for
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| # Aufruf change suffix datei(en)
| |
| if [# -lt 2 ] ; then
| |
| echo "Usage: `basename0` suffix file(s)"
| |
| else
| |
| SUFF=$1 # Suffix speichern
| |
| shift
| |
| for FILE
| |
| do
| |
| mvFILE{FILE}.$SUFF # umbenennen
| |
| shift
| |
| done
| |
| fi
| |
| </syntaxhighlight>
| |
|
| |
| === until ===
| |
| Diese Anweisung ist identisch zu einer <tt>while</tt>-Schleife mit negierter Bedingung
| |
|
| |
| Als Bedingung kann nicht nur eine "klassische" Bedingung (<tt>test</tt> oder <tt>[ ]</tt>) sondern auch der Ergebniswert eines Kommandos oder einer Kommandofolge verwendet werden
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| until Bedingung
| |
| do
| |
| Kommandofolge
| |
| done
| |
| </syntaxhighlight>
| |
|
| |
| Die Schleife wird so lange abgearbeitet, bis Bedingungsausdruck einen Wert ungleich Null liefert
| |
|
| |
| ; Beispiel
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| # warten auf Datei foo
| |
| until [ -f foo ]
| |
| do
| |
| sleep 10
| |
| done
| |
| </syntaxhighlight>
| |
|
| |
| ; Warten auf einen Benutzer
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| # warten, bis sich der Benutzer hans eingeloggt hat
| |
| TT=`who | grep -c "hans"`
| |
| until [TT -gt 0 ]
| |
| do
| |
| sleep 10
| |
| TT=`who | grep -c "hans"`
| |
| done
| |
| # warten, bis sich der Benutzer hans eingeloggt hat
| |
| # Variante 2 - kuerzer
| |
| until [ `who | grep -c "hans"` -gt 0 ]
| |
| do
| |
| sleep 10
| |
| done
| |
| </syntaxhighlight>
| |
|
| |
| Die Befehle werden ausgeführt, bis die Bedingung erfüllt ist. Die Bedingung wird dabei üblicherweise, genau wie bei der if-Anweisung, mit dem Befehl test formuliert
| |
|
| |
| Wenn die Ausführung eines Schleifendurchlaufs bzw. der ganzen Schleife abgebrochen werden soll, müssen die Kommandos continue bzw. break benutzt werden
| |
|
| |
| ; Beispiel
| |
| Hier wird die Bedingung nicht per test, sondern mit dem Rückgabewert des Programms grep formuliert
| |
| <syntaxhighlight lang="bash" highlight="" line copy>
| |
| #!/bin/sh
| |
| # Warten, bis sich der Administrator einloggt
| |
|
| |
| until who | grep "root"; do
| |
| # who: Liste der Benutzer
| |
| # grep: Suchen nach Muster
| |
| sleep 30 # sleep: warten
| |
| done
| |
| echo "Der Meister ist anwesend"
| |
| </syntaxhighlight>
| |
|
| |
|
| [[Kategorie:Bash/Scripting]] | | [[Kategorie:Bash/Scripting]] |
|
| |
| = TMP = === Bedingte Ausführung ===
| |
|
| |
| Die auch als '''Flusskontrolle '''bekannten Mechanismen ermöglichen eine kontrollierte Beeinflussung des Programmablaufs. Die Bash stellt die '''if...fi '''und '''case...esac '''-Konstrukte zur Verfügung.
| |
|
| |
| Erstere Form wird meist zur Unterscheidung einiger weniger Fälle (meist 2) verwendet. Die Syntax lautet:
| |
|
| |
| '''if '''Liste von Kommandos; '''then'''
| |
| Liste von Kommandos
| |
| '''[elif''' Liste von Kommandos; '''then'''
| |
| Liste von Kommandos]
| |
| '''[else'''
| |
| Liste von Kommandos]
| |
| '''fi'''
| |
|
| |
| Von den angegebenen Zweigen werden die Kommandos höchstens eines Zweiges ausgeführt. Entweder die des ersten Zweiges, dessen Bedingung erfüllt ist oder der optionale "else"-Zweig, falls keine Bedingung erfüllt wurde.
| |
|
| |
| Die Bedingung selbst ist der Rückgabewert der Liste der Kommandos (meist also der Rückgabewert des letzten Kommandos der Liste).
| |
|
| |
| Das "case"-Konstrukt wird bei einer höheren Anzahl an Auswahlkriterien bevorzugt. Prinzipiell kann mittels "case" jede "if"-Bedingung abgebildet werden.
| |
|
| |
| Ein wesentlicher Unterschied ist die mögliche Abarbeitung mehrerer Fälle, da alle Anweisungen ab der ersten zutreffenden Bedingung bis zu einem expliziten Verlassen des Konstrukts ausgeführt werden (d.h. ist eine Bedingung erfüllt, werden die nachfolgenden ignoriert).
| |
|
| |
| '''case''' Bedingung '''in'''
| |
| Muster [ | Muster ])
| |
| Liste von Kommandos
| |
| [;;]
| |
| [Muster [ | Muster ])
| |
| Liste von Kommandos
| |
| [;;]]
| |
| '''esac'''
| |
|
| |
| Die Bedingung muss ein Token sein. Die Muster unterliegen denselben Expansionen wie Pfadnamen und dürfen somit Metazeichen enthalten.
| |
|
| |
| Stimmt ein Muster mit der Bedingung überein, werden alle nachfolgenden Kommandos bis zum Verlassen des Konstrukts mittels ";;" oder bis zum abschließenden "esac" ausgeführt.
| |
|
| |
| Der typische Anwendungsbereich für "if"- und "case"-Konstrukte ist die Shellprogrammierung und in diesem Zusammenhang werden Ihnen noch genügend Beispiele zur Benutzung begegnen.
| |
|
| |
| '''if test $(id | awk -F'[=(]' '{print $2}';) -eq "0"; then echo Superuser; else echo Normaler User; fi'''
| |
| Normaler User
| |
| '''su -'''
| |
| Password:
| |
| [mailto:root@lincln01 root@][mailto:root@lincln01 lincln01]> '''if test $(id | awk -F'[=(]' '{print $2}';) -eq "0"; then echo Superuser; else echo Normaler User; fi'''
| |
| Superuser
| |
|
| |
| Das (zugegeben... etwas konstruierte) Beispiel entscheidet, ob der aufrufende Benutzer als Root oder als "normaler" Nutzer arbeitet.
| |
|
| |
| Die Verwendung des builtin-Kommandos '''test '''ist typisch für Bedingungen.
| |
|
| |
|
| |
| [[Kategorie:Bash]]
| |