Kurz: for i in {1..5}; do printf “%d ” “i"; done; echo for i in {10..0..5}; do printf "%d " "i”; done; echo
Teil des Kurses Bash
for über eine Liste
for farbe in rot grün blau; do
echo "Farbe: $farbe"
done
for i in {1..5}; do printf "%d " "$i"; done; echo
for i in {10..0..5}; do printf "%d " "$i"; done; echo
for ((i = 0; i < 3; i++)); do echo "Zähler $i"; done # C-Stil
summe=0
for n in 1 2 3 4; do summe=$((summe + n)); done
echo "Summe: $summe"Ausgabe:
Farbe: rot
Farbe: grün
Farbe: blau
1 2 3 4 5
10 5 0
Zähler 0
Zähler 1
Zähler 2
Summe: 10Über Dateien
Nutze Globs, niemals for f in $(ls) (zerbricht bei Leerzeichen):
cd "$(mktemp -d)"
touch "a b.txt" c.txt d.md
for datei in *.txt; do
echo "Datei: [$datei] hat $(wc -c < "$datei") Bytes"
done
for datei in *.nix; do
[[ -e $datei ]] || { echo "keine .nix-Dateien"; break; }
doneAusgabe:
Datei: [a b.txt] hat 0 Bytes
Datei: [c.txt] hat 0 Bytes
keine .nix-Dateienwhile und until
n=3
while [[ $n -gt 0 ]]; do
echo "n=$n"
((n--))
done
i=0
until [[ $i -ge 3 ]]; do
echo "i=$i"
((i++))
doneAusgabe:
n=3
n=2
n=1
i=0
i=1
i=2Zeilen lesen
while read verarbeitet Eingaben zeilenweise. Setze IFS= und -r, damit nichts verändert wird:
printf "Mia 17\nTom 25\nZoe 31\n" | while IFS=' ' read -r name alter; do
echo "$name ist $alter"
done
while IFS=, read -r land hauptstadt; do
echo "$hauptstadt ist die Hauptstadt von $land"
done <<'DATEN'
Deutschland,Berlin
Frankreich,Paris
DATEN
mapfile -t zeilen < <(printf "eins\nzwei\ndrei\n")
echo "${#zeilen[@]} Zeilen, zweite: ${zeilen[1]}"Ausgabe:
Mia ist 17
Tom ist 25
Zoe ist 31
Berlin ist die Hauptstadt von Deutschland
Paris ist die Hauptstadt von Frankreich
3 Zeilen, zweite: zweiAchtung
In
befehl | while read ...läuft die Schleife in einer Unter-Shell; Variablen, die du darin setzt, sind danach weg. Nutze stattdessenwhile ...; done < <(befehl).
zaehler=0
printf "a\nb\nc\n" | while read -r x; do ((zaehler++)); done
echo "mit Pipe: $zaehler"
zaehler=0
while read -r x; do ((zaehler++)); done < <(printf "a\nb\nc\n")
echo "mit Prozess-Ersetzung: $zaehler"Ausgabe:
mit Pipe: 0
mit Prozess-Ersetzung: 3break, continue, select
for i in {1..10}; do
(( i % 2 == 0 )) && continue # gerade überspringen
(( i > 7 )) && break # abbrechen
printf "%d " "$i"
done
echo
for i in 1 2; do
for j in a b c; do
[[ $j == b ]] && continue 2 # äußere Schleife fortsetzen
echo "$i$j"
done
doneAusgabe:
1 3 5 7
1a
2aMuster: Wiederholen bis es klappt
versuch=0
max=3
until (( versuch >= max )); do
((versuch++))
echo "Versuch $versuch"
if (( versuch == 2 )); then echo "geklappt"; break; fi
doneAusgabe:
Versuch 1
Versuch 2
geklapptMerke
for x in liste; do ... done, Bereiche{1..10}, C-Stil((i=0;i<n;i++))- Dateien per Glob (
*.txt), nicht per$(ls) while/untilmit Bedingung;while IFS= read -r zeile; do ... done < datei- Pipe in
whileläuft in einer Unter-Shell: Prozess-Ersetzung< <(...)nutzen breakundcontinue(auch mit Ebenenzahl)
Übungsaufgabe
Gib alle Zahlen von 1 bis 30 aus, ersetze Vielfache von 3 durch “Fizz”, von 5 durch “Buzz”.
Quiz zur Selbstkontrolle
Wie durchläuft man Dateien sicher?
- *for f in .txt (richtig)
- for f in $(ls)
- for f in ls *.txt
- while ls
Was liefert {1..4}?
- 1 2 3 4 (richtig)
- 1 4
- 0 1 2 3
- {1..4}
Warum gehen Variablen in cmd | while read ... verloren?
- Die Schleife läuft in einer Unter-Shell (richtig)
- read löscht sie
- Bash kennt keine Variablen
- Die Pipe ist zu langsam
Weiter im Kurs
Zurück: Bedingungen und Tests
Weiter: Funktionen und Argumente
Alle Kapitel: Bash im Überblick