Dies ist in dem Bash FAQ-Eintrag auf reading data line-by-line bedeckt.
Der Lesebefehl ändert jede gelesene Zeile; Standardmäßig werden alle führenden und nachfolgenden Leerzeichen (Leerzeichen und Tabulatoren oder Leerzeichen in IFS) entfernt. Wenn das nicht gewünscht ist, muss die IFS-Variable gelöscht werden:
# Exact lines, no trimming
while IFS= read -r line; do
printf '%s\n' "$line"
done < "$file"
Als Charles Duffy zu Recht ausführt (und ich hatte durch die Konzentration auf die IFS
Ausgabe verpasst); Wenn Sie die Leerzeichen in Ihrer Ausgabe sehen wollen, müssen Sie auch die Variable zitieren, wenn Sie sie verwenden, oder die Shell wird wieder das Leerzeichen löschen.
Hinweise zu einigen anderen Unterschieden in diesem zitierten Snippet im Vergleich zu Ihrem ursprünglichen Code.
Die Verwendung des Arguments -r
zu read
wird in einem einzigen Satz oben auf der zuvor verknüpften Seite behandelt.
Die Option -r zum Lesen verhindert die umgekehrte Schrägstrich-Interpretation (wird normalerweise als Backslash-Zeilenumbruchpaar verwendet, um über mehrere Zeilen hinweg fortgesetzt zu werden). Ohne diese Option werden alle umgekehrten Schrägstriche in der Eingabe verworfen. Sie sollten fast immer die Option -r beim Lesen verwenden.
Als printf
statt echo
es das Verhalten von echo
zu verwenden ist, etwas leider nicht portabel konsistent in allen Umgebungen und die Unterschiede umständlich sein kann, zu behandeln. printf
ist dagegen konsistent und kann völlig robust eingesetzt werden.
Wenn Sie keine 'read'-Argumente angeben, um die Eingabe zu halten (die Standardvariable' REPLY' wird verwendet), wird kein Leerzeichen entfernt und Sie können die Änderung an 'IFS' weglassen. Das heißt, während Read -r; tue printf '% s \ n' "$ REPLY"; done <"$ file" ' – chepner
@chepner Interessant. Ich frage mich, warum das so ist. –
Ich bin mir nicht sicher; Soweit ich weiß, scheint es nicht dokumentiert zu sein. Es macht einen Sinn, wenn Sie daran denken, dass Zero-Argumente erfordern, dass die Zeile in Nullfelder aufgeteilt wird, was bedeutet, dass es für "IFS" keine Verwendung gibt. (Das setzt voraus, dass Sie akzeptieren, dass das Aufspalten einer Linie in ein Feld immer noch ein Split ist, wenn auch ein degenerierter.) In jedem Fall ist es ein 'Bash'ism; POSIX 'read' benötigt mindestens ein Argument. – chepner