Eu estava lendo sobre gramática de shell no manual e me deparei com o seguinte
Comandos simples
Um comando simples é uma sequência de atribuições de variáveis opcionais seguidas por palavras separadas por espaços em branco e redirecionamentos, e terminadas por um operador de controle.
Então decidi testar isso com o seguinte script:
#!/usr/bin/bash
if myVar=hello [ "$myVar" ]; then echo "$myVar"; else echo fail "$myVar"; fi
$ ./test.sh
fail
Não consigo ver por que isso falha, se meu entendimento do manual estiver correto, isso deve funcionar. Ao tentar esse script no ShellCheck, recebo o seguinte aviso:
SC2097 (aviso): Esta atribuição só é vista pelo processo bifurcado.
E a explicação é:
Em
name=World cmd "$name"
,name=World
é passado como parte do ambiente paracmd
(ou seja, noenvp
parâmetro para execve(2)). Isso significa quecmd
e seus filhos verão o parâmetro, mas nenhum outro processo verá.
Onde esse comportamento está documentado no manual? Em nenhum lugar diz que as atribuições inline (acabei de inventar esse termo) são locais para o comando em que são declaradas. Além disso, isso não explica por que o script falha. Por essa lógica, [ deve ter acesso a myVar
, executar o bloco then e o script não deve imprimir nada.
O que estou perdendo?
A seção que você está lendo explica apenas a sintaxe, não a semântica. Para a última, veja a seção " Expansão de Comando Simples " no manual do bash.
Então, primeiro, note que expansões, que incluem substituição
$myVar
pelo valor demyVar
, são feitas (etapa 2) antes da atribuição ser realizada (etapa 4). Assim,$myVar
é substituído pelo valor anteriormyVar
de , que está vazio.Além disso, como destaquei em negrito, mesmo quando a atribuição é realizada, ela é somente no ambiente do comando executado, a saber
[
. Então, ela não será visível para nenhum outro comando, como aqueles nas cláusulasthen
orelse
. Este é um recurso, pois fornece uma maneira de executar um único comando com um valor diferente para uma variável específica, sem ter que salvar e restaurar manualmente o valor da variável em torno do comando.