HOWTO · Linux
Wie man eine Datei Zeile für Zeile mit Bash liest
Wir verwenden den Lesebefehl in der Bash, um eine Datei Zeile für Zeile zu lesen.
Auf dieser Seite
Mit dem Befehl read in einer while-Schleife kann Bash eine Textdatei Zeile für Zeile verarbeiten. Die Eingabe wird dabei fortlaufend verarbeitet, sodass das Skript nicht die gesamte Datei im Speicher halten muss. Verwende IFS=, um führende und nachgestellte Leerzeichen zu erhalten, -r, um Backslashes beizubehalten, und setze "$line" bei jeder Verwendung des Werts in Anführungszeichen.
Eine Datei mit einer while-Schleife Zeile für Zeile lesen
Eine zuverlässige Schleife liest die Datei über eine Eingabeumleitung ein. Die Bedingung || [[ -n $line ]] sorgt außerdem dafür, dass die Schleife die letzte Zeile verarbeitet, wenn die Datei keinen abschließenden Zeilenumbruch enthält. Die Datei wird als Datenstrom verarbeitet, und die laufende Summe bleibt in der aktuellen Shell erhalten.
Das vollständige Beispiel unten erstellt seine numerische Eingabedatei selbst, gibt jeden Wert aus und addiert alle sechs Zahlen: 1, 5, 6, 7, 8 und 10. Ihre Summe beträgt 37. Die Beschriftungen und angezeigten Ausgabetexte im unveränderten Beispiel sind weiterhin auf Englisch: Sie kündigen die jeweils ausgegebene Zahl an und nennen abschließend die Gesamtsumme 37.
#!/usr/bin/env bash
set -u
file=$(mktemp)
trap 'rm -f "$file"' EXIT
printf '%s\n' 1 5 6 7 8 10 > "$file"
sum=0
printf 'The numbers in the file are:\n'
while IFS= read -r line || [[ -n $line ]]; do
printf '%s\n' "$line"
sum=$((sum + line))
done < "$file"
printf 'The sum of the numbers in the file is:%s\n' "$sum"
The numbers in the file are:
1
5
6
7
8
10
The sum of the numbers in the file is:37
Eine Eingabeumleitung lässt die Schleife in der aktuellen Shell laufen. Dadurch bleiben Änderungen wie die laufende Summe auch nach der Schleife verfügbar. Vermeide eine nicht in Anführungszeichen gesetzte Erweiterung wie $line: Wortaufteilung und Dateinamenerweiterung können den Inhalt verändern.
Jede Zeile in Felder aufteilen
Um Datensätze anhand eines Trennzeichens aufzuteilen, lies zuerst jede unveränderte Zeile ein und weise anschließend ihre Felder zu. Bei einem read-Aufruf mit Trennzeichen erhält die letzte read-Variable die verbleibenden Felder. Dieses Beispiel erstellt und verarbeitet alle fünf Datensätze: Rohit-10, Harish-30, Manish-50, Kapil-10 und Anish-20. Die Prüfung der letzten Zeile verarbeitet auch einen nicht leeren letzten Datensatz, wenn die Datei keinen abschließenden Zeilenumbruch enthält.
#!/usr/bin/env bash
set -u
file=$(mktemp)
trap 'rm -f "$file"' EXIT
printf '%s\n' 'Rohit-10' 'Harish-30' 'Manish-50' 'Kapil-10' 'Anish-20' > "$file"
while IFS= read -r line || [[ -n $line ]]; do
IFS=- read -r name earnings <<< "$line"
printf '%s has made earnings of %s pounds today!\n' "$name" "$earnings"
done < "$file"
Rohit has made earnings of 10 pounds today!
Harish has made earnings of 30 pounds today!
Manish has made earnings of 50 pounds today!
Kapil has made earnings of 10 pounds today!
Anish has made earnings of 20 pounds today!
Hier legt IFS=- den Bindestrich als Trennzeichen für das Einlesen und Zuweisen der Felder fest. Bei zwei Variablen erhält name den Text vor dem ersten Bindestrich und earnings den Rest. Setze die Variablen beim Ausgeben in Anführungszeichen, damit ihre Inhalte jeweils als einzelner Wert übergeben werden.
Eine andere Methode zum Lesen von Bash-Dateien wählen
Verwende das Muster while IFS= read -r line, wenn du jede Zeile direkt nach dem Einlesen verarbeiten möchtest oder die Datei größer als der verfügbare Speicher sein könnte. Bei einer regulären Datei leite sie direkt in die Schleife um; cat über eine Prozesssubstitution auszuführen bringt hier keinen Vorteil. Eine Prozesssubstitution kann nützlich sein, wenn die Schleife statt einer Datei die erzeugte Ausgabe eines Befehls einlesen soll.
Wenn deine Bash-Installation mapfile bereitstellt, kannst du damit Dateizeilen in ein Array laden, zum Beispiel mit mapfile -t lines < "$file". Wähle diese Methode, wenn spätere Schritte einen indizierten Zugriff oder mehrere Durchläufe über die Zeilen benötigen und die gesamte Datei in den Speicher passt. Die Option -t entfernt den abschließenden Zeilenumbruch jeder Zeile. Ob mapfile verfügbar ist, hängt von der Bash-Installation ab. Wenn du eine breiter einsetzbare Methode brauchst, verwende daher die Streaming-Schleife.