Sie müssen Leerzeichen aus dem $IFS
Parameter entfernen read
, um das Überspringen führender und nachfolgender Zeichen zu beenden (wobei -n1
das Leerzeichen, falls vorhanden, sowohl führende als auch nachfolgende Zeichen ist, also übersprungen):
while IFS= read -rn1 a; do printf %s "$a"; done
Aber selbst dann read
überspringen Bashs Zeilenumbruchzeichen, mit denen Sie umgehen können:
while IFS= read -rn1 a; do printf %s "${a:-$'\n'}"; done
Obwohl Sie IFS= read -d '' -rn1
stattdessen oder sogar besser IFS= read -N1
(hinzugefügt in 4.1, kopiert von ksh93
(hinzugefügt in o
)) verwenden können, ist dies der Befehl zum Lesen eines Zeichens.
Beachten Sie, dass Bashs read
nicht mit NUL-Zeichen umgehen können. Und ksh93 hat die gleichen Probleme wie bash.
Mit zsh:
while read -ku0 a; do print -rn -- "$a"; done
(zsh kann mit NUL-Zeichen umgehen).
Beachten Sie, dass diese read -k/n/N
eine Anzahl von Zeichen und keine Bytes lesen . Bei Multibyte-Zeichen müssen sie möglicherweise mehrere Bytes lesen, bis ein vollständiges Zeichen gelesen wird. Wenn die Eingabe ungültige Zeichen enthält, erhalten Sie möglicherweise eine Variable, die eine Folge von Bytes enthält, die keine gültigen Zeichen bilden und die die Shell möglicherweise als mehrere Zeichen zählt . Zum Beispiel in einem UTF-8-Gebietsschema:
$ printf '\375\200\200\200\200ABC' | bash -c '
IFS= read -rN1 a; echo "${#a}"'
6
Das \375
würde ein 6-Byte-UTF-8-Zeichen einführen. Das sechste ( A
) oben ist jedoch für ein UTF-8-Zeichen ungültig. Sie erhalten immer noch \375\200\200\200\200A
in $a
, was bash
als 6 Zeichen zählt, obwohl die ersten 5 keine wirklichen Zeichen sind, sondern nur 5 Bytes, die nicht Teil eines Zeichens sind.
IFS
nichts ein, damit Leerzeichen die Wortaufteilung überleben.