unset myVariable i;
while [ -z "$i" ]; do
read myVariable;
echo "myVariable : '$myVariable'";
i=foo;
done;
echo "myVariable : '$myVariable'"
(o unset
está lá para permitir a repetição do comando)
pressione qualquer tecla + ENTER, você obterá:
myVariable : '[what you typed]'
myVariable : '[what you typed]'
O valor de myVariable
existe fora do while
loop. Agora tente :
tmpFile=$(mktemp);
echo -e 'foo\nbar\nbaz' >> "$tmpFile"
while read myVariable; do
otherVariable=whatever;
echo "myVariable : '$myVariable', otherVariable : '$otherVariable'";
done < "$tmpFile";
echo "myVariable : '$myVariable', otherVariable : '$otherVariable'";
rm "$tmpFile"
você terá :
myVariable : 'foo', otherVariable : 'whatever'
myVariable : 'bar', otherVariable : 'whatever'
myVariable : 'baz', otherVariable : 'whatever'
myVariable : '', otherVariable : 'whatever'
O valor de myVariable
é perdido ao sair do loop.
Por que há um comportamento diferente? Existe um truque de escopo que eu não conheço?
NB: rodando GNU bash, versão 4.4.12(1)-release (x86_64-pc-linux-gnu)
Não,
myVariable
tem o valor que obteve do últimoread
. O script lê do arquivo, até chegar à posição após a última nova linha. Depois disso, a chamada finalread
não obtém nada do arquivo, definemyVariable
a string vazia de acordo e sai com um valor falso, pois não viu o delimitador (nova linha). Então o laço termina.Você pode obter um valor não vazio do final
read
se houver uma linha incompleta após a última nova linha:Ou use
while read a || [ "$a" ]; do ...
para manipular o fragmento de linha final dentro do corpo do loop.Nesse caso, o
done < "$tmpFile"
redirecionamento força o bash a gerar um sub-shell (como para o pipe).Citado do escopo da variável bash no Stack Overflow.
Seu segundo exemplo usa um
while
loop que tem uma entrada redirecionada.Ele lê using
< "$tmpFile"
e muitos shells criam um subshell para este caso. Você pode tentar executar este script comksh93
.ksh93
não cria um sub-shell neste caso.No seu caso específico, o motivo é completamente diferente:
no primeiro exemplo, você lê uma linha da entrada
no segundo exemplo, você lê até que
EOF
seja alcançadoO
read
comando lê a entrada, então divide a entrada emIFS
caracteres e então atribui palavras aos argumentos variáveis deread
.Se houver mais palavras do que variáveis como parâmetros para o
read
comando, a última variável obtém uma concatenação do restante das palavras.Se houver menos palavras do que variáveis, as outras variáveis receberão um valor vazio.
Desde que você bateu
EOF
, você não tem nenhuma palavra lida, mas uma ou mais variáveis como argumento pararead
. Isso faz com que todas as variáveis obtenham um valor vazio atribuído.Então, algo aconteceu que você não esperava:
EOF
faz com que owhile
loop seja encerrado e você não veja nenhumecho
comando de dentro dowhile
loop, mas apenas oecho
comando final após owhile
loop nesteEOF
caso.Este final
echo
agora imprime o conteúdo da variável que foi limpo de baterEOF
.