Ich habe die folgende TXT-Datei:
Marco
Paolo
Antonio
Ich möchte es Zeile für Zeile lesen und für jede Zeile möchte ich einer Variablen einen TXT-Zeilenwert zuweisen. Angenommen, meine Variable ist $name
, der Fluss ist:
- Lesen Sie die erste Zeile aus der Datei
- Assign
$name
= "Marco" - Machen Sie einige Aufgaben mit
$name
- Lesen Sie die zweite Zeile aus der Datei
- Assign
$name
= "Paolo"
Antworten:
Im Folgenden wird eine Datei gelesen, die zeilenweise als Argument übergeben wird:
Dies ist das Standardformular zum Lesen von Zeilen aus einer Datei in einer Schleife. Erläuterung:
IFS=
(oderIFS=''
) verhindert, dass führende / nachfolgende Leerzeichen abgeschnitten werden.-r
verhindert, dass Backslash-Escapezeichen interpretiert werden.Oder Sie können es in ein Bash-Datei-Hilfsskript einfügen, Beispielinhalt:
Wenn das oben Gesagte in einem Skript mit Dateiname gespeichert ist
readfile
, kann es wie folgt ausgeführt werden:Wenn die Datei keine Standard-POSIX-Textdatei ist (= nicht durch ein Zeilenumbruchzeichen abgeschlossen), kann die Schleife so geändert werden, dass nachfolgende Teilzeilen verarbeitet werden:
|| [[ -n $line ]]
Verhindert hier, dass die letzte Zeile ignoriert wird, wenn sie nicht mit a endet\n
(daread
ein Exit-Code ungleich Null zurückgegeben wird, wenn EOF auftritt).Wenn die Befehle in der Schleife auch aus der Standardeingabe gelesen werden, kann der von verwendete Dateideskriptor
read
auf etwas anderes geändert werden (vermeiden Sie die Standarddateideskriptoren ), z.(Nicht-Bash-Muscheln wissen es möglicherweise nicht
read -u3
; verwenden Sie sieread <&3
stattdessen.)quelle
ssh
das-n
Flag nicht verwenden, können Sie die Schleife effektiv verlassen. Es gibt wahrscheinlich einen guten Grund dafür, aber es hat eine Weile gedauert, bis ich herausgefunden habe, warum mein Code fehlgeschlagen ist, bevor ich dies entdeckt habe.ffmpeg
Konsum von stdin verursacht. Fügen Sie</dev/null
Ihrerffmpeg
Zeile hinzu, und es wird nicht möglich sein oder eine alternative FD für die Schleife verwenden. Dieser "alternative FD" -Ansatz sieht so auswhile IFS='' read -r line <&3 || [[ -n "$line" ]]; do ...; done 3<"$1"
..sh
Erweiterung. Ausführbare Dateien unter UNIX haben normalerweise überhaupt keine Erweiterungen (Sie werden nicht ausgeführtls.elf
), und ein Bash Shebang (und nur Bash-Tools wie[[ ]]
) und eine Erweiterung, die POSIX sh-Kompatibilität impliziert, sind intern widersprüchlich.Ich ermutige Sie, die
-r
Flagge zu verwenden, fürread
die steht:Ich zitiere aus
man 1 read
.Eine andere Sache ist, einen Dateinamen als Argument zu nehmen.
Hier ist aktualisierter Code:
quelle
sh
nicht warbash
; Der erweiterte|| [[ -n "$line" ]]
Testbefehl, der in der Syntax der akzeptierten Antwort verwendet wird, ist ein Bashismus. Diese Syntax hat jedoch tatsächlich eine relevante Bedeutung: Sie bewirkt, dass die Schleife für die letzte Zeile in der Eingabedatei fortgesetzt wird, auch wenn sie keine neue Zeile enthält. Wenn Sie dies auf POSIX-kompatible Weise tun möchten|| [ -n "$line" ]
, möchten Sie lieber verwenden[
als[[
.IFS=
um dasread
Trimmen von Leerzeichen zu verhindern.Die Verwendung der folgenden Bash-Vorlage sollte es Ihnen ermöglichen, jeweils einen Wert aus einer Datei zu lesen und zu verarbeiten.
quelle
*
.quelle
Enter
nach der letzten Zeile gedrückt werden muss), damit sie funktioniert. Andernfalls wird die letzte Zeile ignoriert. Zumindest ist mir das passiert.Viele Leute haben eine Lösung veröffentlicht, die überoptimiert ist. Ich denke nicht, dass es falsch ist, aber ich denke demütig, dass eine weniger optimierte Lösung wünschenswert sein wird, damit jeder leicht verstehen kann, wie dies funktioniert. Hier ist mein Vorschlag:
quelle
Verwenden:
Wenn Sie
IFS
anders eingestellt haben, erhalten Sie ungerade Ergebnisse.quelle
*
in einer Zeile enthält? Jedenfalls ist dies ein Antimuster . Lies keine Zeilen mit für .read
Ansatz ist der Best-Practice-Ansatz im Konsens der Gemeinschaft . Die Einschränkung, die Sie in Ihrem Kommentar erwähnen, gilt, wenn Ihre Schleife Befehle (z. B.ffmpeg
) ausführt, die aus stdin gelesen werden. Dies wird trivial gelöst, indem ein Nicht-stdin-FD für die Schleife verwendet oder die Eingabe solcher Befehle umgeleitet wird. Im Gegensatzfor
dazu bedeutet das Umgehen des Globbing- Fehlers in Ihrem -loop-Ansatz, dass Änderungen an den Shell-globalen Einstellungen vorgenommen werden (und dann rückgängig gemacht werden müssen).for
Schleifenansatz, dass der gesamte Inhalt eingelesen werden muss, bevor die Schleife überhaupt ausgeführt werden kann. Dies macht ihn völlig unbrauchbar, wenn Sie Gigabyte an Daten durchlaufen, selbst wenn Sie diese deaktiviert haben Globbing; Diewhile read
Schleife muss nicht mehr als die Daten einer einzelnen Zeile gleichzeitig speichern. Dies bedeutet, dass sie ausgeführt werden kann, während der Inhalt zur Erzeugung des Unterprozesses noch ausgeführt wird (und somit für Streaming-Zwecke verwendet werden kann). Außerdem ist der Speicherverbrauch begrenzt.while
scheinen selbstbasierte Ansätze Probleme mit * -Zeichen zu haben. Siehe Kommentare der akzeptierten Antwort oben. Nicht dagegen zu argumentieren, dass Dateien ein Antimuster sind.Wenn Sie sowohl die Eingabedatei als auch die Benutzereingabe (oder etwas anderes von stdin) verarbeiten müssen, verwenden Sie die folgende Lösung:
Basierend auf der akzeptierten Antwort und dem Tutorial zur Weiterleitung von Bash-Hackern .
Hier öffnen wir den Dateideskriptor 3 für die als Skriptargument übergebene Datei und weisen
read
an, diesen Deskriptor als input (-u 3
) zu verwenden. Daher belassen wir den Standardeingabedeskriptor (0) an einem Terminal oder einer anderen Eingabequelle, der Benutzereingaben lesen kann.quelle
Für eine ordnungsgemäße Fehlerbehandlung:
quelle
Im Folgenden wird nur der Inhalt der Datei ausgedruckt:
quelle
Verwenden Sie das IFS-Tool (Internal Field Separator) in Bash. Definiert das Zeichen, mit dem Zeilen in Token getrennt werden. Standardmäßig enthält es < tab > / < Leerzeichen > / < newLine >
Schritt 1 : Laden Sie die Dateidaten und fügen Sie sie in die Liste ein:
Schritt 2 : Jetzt iterieren und drucken Sie die Ausgabe:
Echospezifischer Index im Array : Zugriff auf eine Variable im Array:
quelle