Seu primeiro palpite estava certo, mas você usou um mau exemplo. Quando o shell lê o comando
foo=bar echo $foo
a primeira coisa que faz (ou, pelo menos, uma das primeiras coisas)
é procurar referências de variáveis (como $foo
) e avaliá-las.
Então processa o que resta da linha.
(Isso pode ser um pouco de simplificação excessiva;
veja bash(1)
ou o Bash Reference Manual para detalhes.)
Então você tem o comando
echo (nothing)
executando com foo=bar
; mas é muito tarde; não resta mais nada para ver o valor de $foo
.
Você pode demonstrar isso com a seguinte sequência:
$ foo=oldvalue
$ foo=bar echo "$foo"
oldvalue
Mas
foo=bar command
é o caminho a percorrer. Alguns exemplos que funcionam são:
foo=bar sh -c 'echo "$foo"'
e
foo=bar env
(Você pode querer canalizar isso através de grep foo
.)
Eu acabei de notar a frase que você citou,
“Quando essas instruções de atribuição precedem um comando embutido no shell, por exemplo,…”,
sugerindo que comandos internos (como echo
) representam um caso especial.
É intuitivo (para mim, pelo menos) que esse "escopo de comando" que você está procurando
teria que trabalhar definindo uma variável de ambiente em um processo filho,
e não está claro como isso funcionaria para um comando interno, que não é executado em um processo filho.
Não há muitos comandos internos que acessam diretamente o ambiente,
e sua interação com variáveis shell é, às vezes, arcanizada.
Mas eu criei mais alguns exemplos que podem ser mais do que você procura:
foo=bar eval 'echo $foo'
exibirá "barra", porque a avaliação de $foo
é adiada.
Ele é manipulado pelo comando eval
(interno), em vez da passagem de análise inicial do shell.
Ou crie um arquivo de texto chamado (por exemplo) showme.sh
.
Coloque um comando echo $foo
(ou echo "$foo"
) nele e diga
foo=bar . showme.sh
Isto é provavelmente o que seu livro está falando quando diz:
“… O shell tem que acompanhar a ordem correta na qual resolver referências de variáveis….”
De alguma forma, o shell executa os comandos em showme.sh
com foo
igual a bar
,
e depois reverte para o valor anterior de foo
(se houver)
quando voltar para sua entrada principal (o terminal).