Zum Inhalt springen

Kategorie:Bash/Kontrollstrukturen: Unterschied zwischen den Versionen

Aus Foxwiki
Zeile 11: Zeile 11:


== Schleifen ==
== Schleifen ==
; for-Anweisung
[[Bash/Schleifen]]
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.&nbsp;der ganzen Schleife abgebrochen werden soll, müssen die Kommandos continue bzw.&nbsp;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.&nbsp;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.&nbsp;der ganzen Schleife abgebrochen werden soll, müssen die Kommandos continue bzw.&nbsp;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.&nbsp;der ganzen Schleife abgebrochen werden soll, müssen die Kommandos continue bzw.&nbsp;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]]


= TMP =  
= TMP =  

Version vom 14. Oktober 2025, 10:16 Uhr

Bash/Kontrollstrukturen - Verzweigungen, Schleifen, Fallunterscheidungen

Beschreibung

Ablauf eines Linux-Shell-Skripts steuern

Bedingungen

Bash/Bedingungen

Fallunterscheidung

Bash/Fallunterscheidung

Schleifen

Bash/Schleifen

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:
root@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.

Seiten in der Kategorie „Bash/Kontrollstrukturen“

Folgende 4 Seiten sind in dieser Kategorie, von 4 insgesamt.