Vous devez supprimer les caractères d'espacement du $IFS
paramètre pour read
arrêter de sauter les caractères de début et de fin (avec -n1
, le caractère d'espacement s'il y en a serait à la fois de début et de fin, donc ignoré):
while IFS= read -rn1 a; do printf %s "$a"; done
Mais même dans ce cas, bash read
ignorera les caractères de nouvelle ligne, avec lesquels vous pouvez contourner:
while IFS= read -rn1 a; do printf %s "${a:-$'\n'}"; done
Bien que vous puissiez utiliser à la IFS= read -d '' -rn1
place ou même mieux IFS= read -N1
(ajouté en 4.1, copié depuis ksh93
(ajouté en o
)) qui est la commande pour lire un caractère.
Notez que bash ne read
peut pas gérer les caractères NUL. Et ksh93 a les mêmes problèmes que bash.
Avec zsh:
while read -ku0 a; do print -rn -- "$a"; done
(zsh peut gérer les caractères NUL).
Notez que ceux-ci read -k/n/N
lisent un certain nombre de caractères , pas d' octets . Ainsi, pour les caractères multi-octets, ils peuvent avoir à lire plusieurs octets jusqu'à ce qu'un caractère complet soit lu. Si l'entrée contient des caractères non valides, vous pouvez vous retrouver avec une variable qui contient une séquence d'octets qui ne forme pas de caractères valides et que le shell peut finir par compter comme plusieurs caractères . Par exemple, dans un environnement local UTF-8:
$ printf '\375\200\200\200\200ABC' | bash -c '
IFS= read -rN1 a; echo "${#a}"'
6
Cela \375
introduirait un caractère UTF-8 de 6 octets. Cependant, le 6ème ( A
) ci-dessus n'est pas valide pour un caractère UTF-8. Vous vous retrouvez toujours avec \375\200\200\200\200A
in $a
, qui bash
compte pour 6 caractères bien que les 5 premiers ne soient pas vraiment des caractères, seulement 5 octets ne faisant partie d'aucun caractère.
IFS
à rien pour que les espaces blancs survivent à la séparation des mots.