Eu posso reproduzir esse comportamento apenas em dois casos:
-
substituição de comando com aspas duplas:
#!/bin/bash str="a b c d" printf "%s\n" "'echo $str'"
-
ou o Separador de campo interno alterado (
IFS
variable), por exemplo:#!/bin/bash IFS=, str="a b c d" printf "%s\n" 'echo $str'
Em ambos os casos, a saída é
$ ./test.sh
a b c d
Para reparar o primeiro caso, apenas remova as aspas e, para restaurar IFS
, configure-o para o valor padrão em algum lugar acima da substituição de comando.
IFS=$' \t\n'
Um pouco de explicação porque a saída é diferente quando IFS
mudou e o que tem em comum com aspas duplas?
Vamos começar do final:
printf "%s\n" a b c d
é obviamente diferente de
printf "%s\n" 'a b c d'
No primeiro caso, temos quatro palavras separadas e printf
envia-as uma a uma, adicionando uma nova linha a elas. No segundo caso, todo o a b c d
é tratado como uma única palavra e printf
apenas o envia como tal para o terminal. E agora deve ser óbvio que a saída de 'echo $str'
é tratada como uma única palavra quando adicionalmente está entre aspas duplas.
Agora é onde IFS
começa a desempenhar um papel. Ou seja, tt é usado para dividir palavras após as expansões, então com o padrão IFS=$' \t\n'
a expressão echo a b c d
outputs a b c d
, mas com IFS=,
ele se torna 'a b c d'
- um único mundo, embora aspas não tenham sido usadas explicitamente. Pode-se verificar isso mais claramente sem variável:
$ IFS=,
$ printf "%s\n" 'echo a b c d'
a b c d
$ IFS=$' \t\n'
$ printf "%s\n" 'echo a b c d'
a
b
c
d
Como nota final: é melhor usar uma forma $()
de substituição de comandos, não de backticks, mas esse é um tópico diferente.