Tenho o seguinte exemplo:
$ a="$(ls)"
$ echo $a
backups cache crash lib local lock log mail opt run snap spool tmp
$
$ echo "$a"
backups
cache
crash
lib
local
lock
log
mail
opt
run
snap
spool
tmp
Agora com printf
:
$ printf $a
backups
$
$ printf "$a"
backups
cache
crash
lib
local
lock
log
mail
opt
run
snap
spool
tmp
Por que a saída é tão diferente? O que as citações fazem nesta situação? Alguém poderia explicar o que está acontecendo aqui?
PS Encontrou alguma explicação sobre o ls
comportamento:
A saída de ls tem novas linhas, mas é exibida em uma única linha. Por quê?
https://superuser.com/questions/424246/what-is-the-magic-separator-between-filenames-in-ls-output
http://mywiki.wooledge.org/ParsingLs
Os caracteres de nova linha podem ser verificados desta forma :
ls | od -c
echo $a
é o mesmo queConsiderando que
echo "$a"
é o mesmo queConsulte https://mywiki.wooledge.org/Quotes .
O primeiro argumento para
printf
é uma string de formatação eprintf $a
é o mesmoprintf backups cache crash lib local lock log mail opt run snap spool tmp
que está usando a stringbackups
como formato e descartando o resto, pois não há nada parecido%s
na string de formatação para usá-los. Assim como:Não
a="$(ls)"
tente criar uma variável escalar contendo nomes de arquivos, pois isso é frágil, façaa=(*)
para mantê-los em uma matriz.Obrigado a @Ed Morton e @Kusalananda pela explicação.
Acho que meu problema foi que sempre pensei que, por padrão,
ls
divide os arquivos usando espaços ou tabulações. Mas, na verdade, ele os separa com novos caracteres de linha, mas gera os arquivos em colunas (classificados verticalmente) ao imprimir em um terminal. Caracteres de nova linha podem ser verificados com:Vou mover a resposta do @Kusalananda da seção de comentários para uma resposta, pois foi útil:
Em suma,
echo
gera seus argumentos com espaços entre eles. Isto é o queecho
faz.Ao usar
echo $a
, o shell divide o conteúdo de$a
em vários argumentos com base em espaços, tabulações e novas linhas (e também faz globbing de nome de arquivo em cada palavra gerada).echo
em seguida, imprime-os com espaços entre eles.Com
echo "$a"
, você só dá ao echo um único argumento. A string"$a"
contém novas linhas da saída dels
, e estas são retidas e emitidas porecho
.