Você tem três problemas:
- Com
read
, se houver menos nomes de variáveis do que campos na entrada, o último var será vinculado a todos os campos restantes na linha, com delimitadores. Isso significa que$e
obtém5 6
em seu primeiro exemplo inesperado. - Como todos os
$a
..$e
não estão registrados, seus valores passam por divisão de campo . Se$e
detiver "5 6
", ele será expandido em dois argumentos para o comando. -
printf
consome todos os seus argumentos, usando tantos argumentos de uma só vez quanto há%
substituições, repetidamente. Isso é inserido na documentação como:The
format
operand shall be reused as often as necessary to satisfy the argument operands. Any extrac
ors
conversion specifiers shall be evaluated as if a null string argument were supplied; other extra conversion specifications shall be evaluated as if a zero argument were supplied.Em outras palavras, se houver argumentos não utilizados, ele será iniciado novamente e processado também desde o início, incluindo toda a cadeia de formatações. Isso é útil quando você deseja formatar uma matriz inteira, por exemplo:
printf '%b ' "${array[@]}"
Seu comando
printf
obtém um argumento de cada um dos$a
..$d
e, em seguida, quantos sobram de$e
. Quando$e
for "5 6
",printf
terá duas, a segunda apenas6
será formatada. Quando é5 6 7 8 9 10
, tem toda a gama de substituições para a segunda impressão.
Você pode evitar tudo isso adicionando um campo dummy extra a read
e citando suas substituições de parâmetro (o que é sempre uma boa ideia):
read a b c d e dummy
printf "> %s %s %s %s %s <" "$a" "$b" "$c" "$d" "$e"
Isso vai dar:
Enter 5 words :
1 2 3 4 5 6 7 8 9 10
> 1 2 3 4 5 <
dummy
obtém todos os campos extras e printf
obtém apenas os cinco argumentos esperados.
Sua segunda pergunta editada tem uma resposta semelhante: somente a
obtém um valor quando IFS
não tem espaço. Isso significa $b
.. $e
expandir para nada, então printf
obtém apenas um único argumento. Seus espaços da string de formatação são impressos, sem nada substituído entre eles ("como se um argumento de string nula fosse fornecido").