È necessario rimuovere i caratteri degli spazi bianchi dal $IFS
parametro per read
interrompere il salto di quelli iniziali e finali (con -n1
, il carattere degli spazi bianchi, se presente, sarebbe sia iniziale che finale, quindi ignorato):
while IFS= read -rn1 a; do printf %s "$a"; done
Ma anche allora bash read
salterà i personaggi newline, con i quali puoi aggirare:
while IFS= read -rn1 a; do printf %s "${a:-$'\n'}"; done
Sebbene tu possa usare IFS= read -d '' -rn1
invece o anche meglio IFS= read -N1
(aggiunto in 4.1, copiato da ksh93
(aggiunto in o
)) quale è il comando per leggere un carattere.
Nota che bash read
non può far fronte ai personaggi NUL. E ksh93 ha gli stessi problemi di bash.
Con zsh:
while read -ku0 a; do print -rn -- "$a"; done
(zsh può far fronte ai caratteri NUL).
Si noti che quelli read -k/n/N
leggono un numero di caratteri , non byte . Pertanto, per i caratteri multibyte, potrebbe essere necessario leggere più byte fino a quando non viene letto un carattere completo. Se l'input contiene caratteri non validi, si può finire con una variabile che contiene una sequenza di byte che non forma caratteri validi e che la shell potrebbe finire per contare come più caratteri . Ad esempio in una locale UTF-8:
$ printf '\375\200\200\200\200ABC' | bash -c '
IFS= read -rN1 a; echo "${#a}"'
6
Ciò \375
introdurrebbe un carattere UTF-8 a 6 byte. Tuttavia, il sesto ( A
) sopra non è valido per un carattere UTF-8. Si finisce ancora con \375\200\200\200\200A
in $a
, che bash
conta come 6 caratteri sebbene i primi 5 non siano realmente personaggi, solo 5 byte che non fanno parte di alcun personaggio.
IFS
nulla per far sì che gli spazi bianchi sopravvivano alla divisione delle parole.