Sie müssen Leerzeichen aus dem $IFSParameter entfernen read, um das Überspringen führender und nachfolgender Zeichen zu beenden (wobei -n1das 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 '' -rn1stattdessen 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 readnicht 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/Neine 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 \375wü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\200Ain $a, was bashals 6 Zeichen zählt, obwohl die ersten 5 keine wirklichen Zeichen sind, sondern nur 5 Bytes, die nicht Teil eines Zeichens sind.
IFSnichts ein, damit Leerzeichen die Wortaufteilung überleben.