---
id: 2024-10-26-bash-grundkurs-ein-und-ausgabe-in-bash
slug: bash-grundkurs-ein-und-ausgabe-in-bash
title: "Bash Grundkurs #5: Ein- und Ausgabe in Bash"
excerpt: "Lerne in diesem Grundkurs, wie du Ein- und Ausgabe in Bash-Skripten nutzt, um Benutzereingaben zu verarbeiten, Daten zu speichern und mit Dateien zu arbeiten."
date: 2024-10-26T09:00:00+01:00
updated: 2024-10-26T09:00:00+01:00
author:
  name: "Sebastian Palencsár"
  handle: "spalencsar"
category: ["bash-grundlagen"]
tags: ["bash", "linux", "programming", "shell"]
reading_time: 15
toc: true
---

**Willkommen zum fünften Artikel unserer technischen Wiki-Serie über Bash-Programmierung!**

In den vorherigen Artikeln hast du gelernt, wie du Skripte erstellst, mit Variablen arbeitest, Kontrollstrukturen verwendest und Funktionen schreibst. Heute lernst du, wie deine Skripte mit der Außenwelt kommunizieren können – durch Ein- und Ausgabe.

## Wie wichtig ist die Ein- und Ausgabe?

Ein Skript, das nicht mit seiner Umgebung kommunizieren kann, ist wie ein Mensch ohne Sinne. Es braucht Möglichkeiten, Informationen aufzunehmen (Eingabe) und Ergebnisse mitzuteilen (Ausgabe).

**In Bash gibt es verschiedene Wege, dies zu tun:**

- Eingaben von der Tastatur lesen
- Text auf dem Bildschirm ausgeben
- Daten in Dateien speichern
- Informationen aus Dateien lesen

Lass uns mit der einfachsten Form der Ausgabe beginnen – dem Anzeigen von Text auf dem Bildschirm.

### Text ausgeben mit echo

Der `echo`-Befehl ist dein wichtigstes Werkzeug für die Ausgabe.

**Du hast ihn bereits in den vorherigen Artikeln kennengelernt:**

```bash
#!/bin/bash

# Einfache Textausgabe
echo "Hallo, willkommen zu Ein- und Ausgabe in Bash!"

# Variablen ausgeben
name="Max"
echo "Hallo $name"

# Mehrere Zeilen ausgeben
echo "Erste Zeile"
echo "Zweite Zeile"
```

### Erweiterte Ausgabemöglichkeiten

**Der echo-Befehl mit Formatierung**

Der `echo`-Befehl kann mehr als nur einfachen Text ausgeben.

**Mit der Option `-e` kannst du spezielle Formatierungen verwenden:**

```bash
#!/bin/bash

# Neue Zeile mit \n
echo -e "Erste Zeile\nZweite Zeile"

# Tabulator mit \t
echo -e "Name:\tMax\nAlter:\t25"

# Text hervorheben
echo -e "\033[1mFett\033[0m"
echo -e "\033[31mRot\033[0m"
echo -e "\033[44mBlauer Hintergrund\033[0m"
```

### Formatierte Ausgabe mit printf

Für noch mehr Kontrolle über das Ausgabeformat gibt es den `printf`-Befehl:

```bash
#!/bin/bash

# Grundlegende printf-Syntax
printf "Hallo, %s!\n" "Max"

# Zahlen formatieren
printf "Nummer: %d\n" 42
printf "Preis: %.2f €\n" 9.99

# Tabelle erstellen
printf "%-10s %5s %8s\n" "Name" "Alter" "Stadt"
printf "%-10s %5d %8s\n" "Max" 25 "Berlin"
printf "%-10s %5d %8s\n" "Anna" 30 "Hamburg"
```

**Wichtig für Anfänger:**

- `%s` ist ein Platzhalter für Text (Strings)
- `%d` ist für ganze Zahlen
- `%f` ist für Dezimalzahlen
- `\n` erzeugt eine neue Zeile
- Die Zahl nach `%` bestimmt die Feldbreite
- `-` links-bündig statt rechts-bündig
- `.2` bei `%.2f` gibt die Anzahl der Dezimalstellen an

## Benutzereingaben einlesen

Der `read`-Befehl ist dein Werkzeug, um Eingaben von der Tastatur zu lesen.

**Lass uns verschiedene Möglichkeiten kennenlernen:**

**Einfache Eingabe**

```bash
#!/bin/bash

# Grundlegende Verwendung von read
echo "Wie heißt du?"
read name
echo "Hallo $name!"

# Mit eigener Eingabeaufforderung
read -p "Wie alt bist du? " alter
echo "Du bist also $alter Jahre alt."
```

**Sichere Eingabe mit Überprüfung**

```bash
#!/bin/bash

# Eingabe mit Überprüfung
while true; do
    read -p "Gib eine Zahl zwischen 1 und 10 ein: " zahl

    # Prüfe, ob die Eingabe eine Zahl ist
    if ! [[ $zahl =~ ^[0-9]+$ ]]; then
        echo "Fehler: Bitte nur Zahlen eingeben!"
        continue
    fi

    # Prüfe den Wertebereich
    if [ $zahl -lt 1 ] || [ $zahl -gt 10 ]; then
        echo "Fehler: Die Zahl muss zwischen 1 und 10 liegen!"
        continue
    fi

    echo "Danke! Du hast $zahl eingegeben."
    break
done
```

**Verschiedene read-Optionen**

```bash
#!/bin/bash

# Zeitlimit für die Eingabe
read -t 5 -p "Du hast 5 Sekunden Zeit zu antworten: " antwort
if [ -z "$antwort" ]; then
    echo -e "\nZeit abgelaufen!"
fi

# Passwort eingeben (ohne Anzeige)
read -s -p "Passwort eingeben: " passwort
echo -e "\nDanke für die Eingabe!"

# Mehrere Werte einlesen
read -p "Gib drei Zahlen ein (durch Leerzeichen getrennt): " zahl1 zahl2 zahl3
echo "Du hast eingegeben: $zahl1, $zahl2 und $zahl3"
```

**Wichtige read-Optionen:**

- `-p` zeigt eine Eingabeaufforderung
- `-s` versteckt die Eingabe (für Passwörter)
- `-t` setzt ein Zeitlimit in Sekunden
- `-n` begrenzt die Anzahl der einzulesenden Zeichen
- `-r` verhindert, dass Backslash als Escape-Zeichen interpretiert wird

### Arbeiten mit Dateien

In Bash gibt es verschiedene Möglichkeiten, mit Dateien zu arbeiten.

Lass uns die wichtigsten Methoden kennenlernen:

**Aus Dateien lesen**

```bash
#!/bin/bash

# Eine Datei zeilenweise lesen
echo "Inhalt der Datei zeilenweise lesen:"
while IFS= read -r zeile; do
    echo "$zeile"
done < "beispiel.txt"

# Kompletten Inhalt auf einmal lesen
inhalt=$(<beispiel.txt)
echo -e "\nKompletter Inhalt:"
echo "$inhalt"

# Bestimmte Zeilen lesen
echo -e "\nNur die erste Zeile:"
head -n 1 beispiel.txt

echo -e "\nNur die letzte Zeile:"
tail -n 1 beispiel.txt
```

**In Dateien schreiben**

```bash
#!/bin/bash

# Neue Datei erstellen oder überschreiben
echo "Das ist die erste Zeile" > neue_datei.txt
echo "Das ist die zweite Zeile" >> neue_datei.txt

# Mehrere Zeilen auf einmal schreiben
cat > mehrere_zeilen.txt << EOF
Zeile 1: Hallo
Zeile 2: Das ist ein Test
Zeile 3: Bash ist toll
EOF

# Inhalt anzeigen
echo "Inhalt der neuen Datei:"
cat neue_datei.txt

echo -e "\nInhalt der mehrere_zeilen.txt:"
cat mehrere_zeilen.txt
```

**Wichtige Operatoren:**

- `>` überschreibt eine Datei
- `>>` hängt an eine Datei an
- `<` liest aus einer Datei
- `<<EOF` ermöglicht Mehrzeilen-Eingabe (Here-Document)

**Dateien überprüfen**

```bash
#!/bin/bash

dateiname="test.txt"

# Prüfe, ob Datei existiert
if [ -f "$dateiname" ]; then
    echo "Die Datei existiert"

    # Prüfe Lese- und Schreibrechte
    if [ -r "$dateiname" ]; then
        echo "Die Datei ist lesbar"
    fi

    if [ -w "$dateiname" ]; then
        echo "Die Datei ist beschreibbar"
    fi
else
    echo "Die Datei existiert nicht"
fi
```

**Wichtige Dateitests:**

- `f` prüft, ob eine reguläre Datei existiert
- `d` prüft, ob ein Verzeichnis existiert
- `r` prüft Leserechte
- `w` prüft Schreibrechte
- `x` prüft Ausführungsrechte
- `s` prüft, ob die Datei nicht leer ist

## Ein- und Ausgabe umleiten

In Bash kannst du die Standardeingabe, -ausgabe und Fehlerausgabe umleiten. Das ist besonders nützlich für die Automatisierung und Protokollierung.

### Grundlegende Umleitungen\*\*

```bash
#!/bin/bash

# Ausgabe in Datei umleiten
echo "Das geht in eine Datei" > ausgabe.txt

# Fehlerausgabe umleiten
ls nicht_existierende_datei 2> fehler.txt

# Beide Ausgaben in verschiedene Dateien umleiten
ls existiert_nicht alle_dateien 1> normal.txt 2> fehler.txt

# Beide Ausgaben in dieselbe Datei umleiten
ls -la &> alle_ausgaben.txt
```

**Wichtige Umleitungsoperatoren:**

- `1> oder >` – Standardausgabe umleiten
- `2>` – Fehlerausgabe umleiten
- `&>` – beide Ausgaben umleiten
- `>>` – an Datei anhängen statt überschreiben
- `<` – Eingabe aus Datei lesen

### Pipes verwenden

Mit Pipes `(|)` kannst du die Ausgabe eines Befehls als Eingabe für einen anderen Befehl verwenden:

```bash
#!/bin/bash

# Zähle Zeilen in einer Datei
cat beispiel.txt | wc -l

# Finde bestimmte Wörter und zähle sie
echo "Apfel Banane Apfel Orange Apfel" | grep -o "Apfel" | wc -l

# Sortiere und zeige nur eindeutige Einträge
echo -e "Zeile 1\nZeile 2\nZeile 1" | sort | uniq
```

🔧 <span class="nb-accent">Praktisches Beispiel</span>

**Logfile-Verarbeitung**

```bash
#!/bin/bash

# Funktion zum Protokollieren
protokolliere() {
    local nachricht="$1"
    local zeitstempel=$(date "+%Y-%m-%d %H:%M:%S")

    # Protokolliere in Datei und zeige auf Bildschirm
    echo "[$zeitstempel] $nachricht" | tee -a protokoll.txt
}

# Beispielverwendung
protokolliere "Skript gestartet"

# Fehler protokollieren
if ! ls nicht_existierend 2>/dev/null; then
    protokolliere "Fehler: Datei nicht gefunden"
fi

protokolliere "Skript beendet"

# Zeige das Protokoll
echo -e "\nInhalt des Protokolls:"
cat protokoll.txt
```

**Wichtige Befehle für die Verarbeitung:**

- `grep` – Suchen nach Text
- `sort` – Sortieren von Zeilen
- `uniq` – Doppelte Zeilen entfernen
- `wc` – Zeilen/Wörter/Zeichen zählen
- `tee` – Ausgabe in Datei und auf Bildschirm

## Übung

Erstelle ein Adressbuch-Skript, das **folgende Anforderungen erfüllt:**

**Das Skript soll:**

- Kontakte hinzufügen können
- Kontakte anzeigen können
- Nach Kontakten suchen können
- Alle Daten in einer Datei speichern

**Für jeden Kontakt sollen:**

- Name
- Telefonnummer
- E-Mail-Adresse gespeichert werden

**Beachte:**

- Überprüfe alle Eingaben auf Gültigkeit
- Speichere die Daten strukturiert
- Behandle mögliche Fehler

**Hier ist eine mögliche Lösung:**

```bash
#!/bin/bash

# Konfiguration
ADRESSBUCH="adressbuch.txt"

# Kontakt hinzufügen
kontakt_hinzufuegen() {
    # Eingaben sammeln
    read -p "Name: " name
    read -p "Telefon: " telefon
    read -p "E-Mail: " email

    # Eingaben überprüfen
    if [ -z "$name" ] || [ -z "$telefon" ] || [ -z "$email" ]; then
        echo "Fehler: Alle Felder müssen ausgefüllt werden"
        return 1
    fi

    # E-Mail-Format prüfen (einfache Prüfung)
    if ! [[ "$email" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
        echo "Fehler: Ungültige E-Mail-Adresse"
        return 1
    fi

    # In Datei speichern
    echo "$name;$telefon;$email" >> "$ADRESSBUCH"
    echo "Kontakt wurde gespeichert"
}

# Kontakte anzeigen
kontakte_anzeigen() {
    if [ ! -f "$ADRESSBUCH" ]; then
        echo "Keine Kontakte vorhanden"
        return
    fi

    echo "=== Adressbuch ==="
    while IFS=';' read -r name telefon email; do
        echo "Name: $name"
        echo "Telefon: $telefon"
        echo "E-Mail: $email"
        echo "----------------"
    done < "$ADRESSBUCH"
}

# Nach Kontakten suchen
kontakt_suchen() {
    read -p "Suchbegriff eingeben: " suche

    if [ ! -f "$ADRESSBUCH" ]; then
        echo "Keine Kontakte vorhanden"
        return
    fi

    echo "=== Suchergebnisse ==="
    grep -i "$suche" "$ADRESSBUCH" | while IFS=';' read -r name telefon email; do
        echo "Name: $name"
        echo "Telefon: $telefon"
        echo "E-Mail: $email"
        echo "----------------"
    done
}
```

## Fazit

In diesem fünften Teil unseres Bash-Grundkurses hast du gelernt, wie deine Skripte mit der Außenwelt kommunizieren können. Du kennst jetzt die verschiedenen Möglichkeiten der Ein- und Ausgabe in Bash, von einfachen Bildschirmausgaben bis hin zur Dateiverarbeitung. Du weißt, wie du Benutzereingaben einliest, diese überprüfst und wie du Daten dauerhaft in Dateien speicherst.

Die Fähigkeit, Ein- und Ausgabe zu verarbeiten, ist fundamental für jedes Bash-Skript. Mit diesem Wissen kannst du nun interaktive Skripte schreiben, Daten verarbeiten und Ergebnisse speichern.

Im nächsten Teil unserer Serie werden wir uns mit der **Fehlerbehandlung und dem Debugging in Bash** beschäftigen. Du wirst lernen, wie du deine Skripte robuster machst und Probleme effektiv findest und behebst.

**Bis dahin, happy scripting!**
