Você precisa remover os caracteres de espaço em branco do parâmetro $IFS
para read
para parar de pular os pontos iniciais e posteriores (com -n1
, o caractere de espaço em branco se algum deles estiver à esquerda e à direita):
while IFS= read -rn1 a; do printf %s "$a"; done
Mas, mesmo assim, o read
do bash irá ignorar caracteres de nova linha, com os quais você pode contornar:
while IFS= read -rn1 a; do printf %s "${a:-$'\n'}"; done
Embora você possa usar IFS= read -d '' -rn1
ou melhor IFS= read -N1
(adicionado em 4.1, copiado de ksh93
(adicionado em o
)), que é o comando para ler um caractere.
Observe que o read
do bash não pode lidar com caracteres NUL. E o ksh93 tem os mesmos problemas que o bash.
Com zsh:
while read -ku0 a; do print -rn -- "$a"; done
(zsh pode lidar com caracteres NUL).
Note que os read -k/n/N
lêem um número de caracteres , não bytes . Portanto, para caracteres multibyte, eles podem ter que ler vários bytes até que um caractere completo seja lido. Se a entrada contiver caracteres inválidos, você pode acabar com uma variável que contém uma seqüência de bytes que não formam caracteres válidos e que o shell pode acabar contando como vários caracteres . Por exemplo, em uma localidade UTF-8:
$ printf '50000ABC' | bash -c '
IFS= read -rN1 a; echo "${#a}"'
6
Esse 5
introduziria um caractere UTF-8 de 6 bytes. No entanto, o sexto ( A
) acima é inválido para um caractere UTF-8. Você ainda acaba com 50000A
em $a
, que bash
conta como 6 caracteres embora os primeiros 5 não sejam realmente caracteres, apenas 5 bytes não fazem parte de nenhum caractere. / p>