A idéia básica é que VAR=VALUE some-command
define VAR
to VALUE
para a execução de some-command
quando some-command
é um comando externo e não fica mais chique do que isso. Se você combinar essa intuição com algum conhecimento de como um shell funciona, você deve encontrar a resposta certa na maioria dos casos. A referência POSIX é “Comandos simples” no capítulo “Linguagem de comando da Shell” .
Se some-command
for um comando externo , VAR=VALUE some-command
será equivalente a env VAR=VALUE some-command
. VAR
é exportado no ambiente de some-command
e seu valor (ou falta de valor) no shell não é alterado.
Se some-command
for uma função , VAR=VALUE some-command
será equivalente a VAR=VALUE; some-command
, ou seja, a atribuição permanecerá em vigor após a função ter retornado e variável não é exportada para o ambiente. A razão para isso tem a ver com o design do shell Bourne (e subsequentemente com compatibilidade retroativa): ele não tinha recursos para salvar e restaurar valores de variáveis em torno da execução de uma função. Não exportar a variável faz sentido, já que uma função é executada no próprio shell. No entanto, ksh (incluindo ATT ksh93 e pdksh / mksh), bash e zsh implementam o comportamento mais útil, em que VAR
é definido apenas durante a execução da função (ela também é exportada). Em ksh , isso é feito se a função for definida com a sintaxe ksh function NAME …
, e não se for definida com a sintaxe padrão NAME ()
. Em bash , isso é feito apenas no modo bash, não no modo POSIX (quando executado com POSIXLY_CORRECT=1
). Em zsh , isso é feito se a opção posix_builtins
não estiver definida; essa opção não é definida por padrão, mas é ativada por emulate sh
ou emulate ksh
.
Se some-command
for embutido, o comportamento dependerá do tipo de builtin. Particulares especiais se comportam como funções. Os built-ins especiais são aqueles que precisam ser implementados dentro do shell, pois afetam o shell de estado (por exemplo, break
afeta o fluxo de controle, cd
afeta o diretório atual, set
afeta os parâmetros posicionais e opções…). Outros recursos internos são incorporados apenas para desempenho e conveniência (principalmente - por exemplo, o recurso bash printf -v
pode ser implementado apenas por um builtin), e eles se comportam como um comando externo.
A atribuição ocorre após a expansão do alias, portanto, se some-command
for um alias , expanda-o primeiro para descobrir o que acontece.
Observe que, em todos os casos, a atribuição é executada após a linha de comando ser analisada, incluindo qualquer substituição de variável na própria linha de comando. Portanto, var=a; var=b echo $var
imprime a
, porque $var
é avaliado antes que a atribuição ocorra. E assim IFS=. printf "%s\n" $var
usa o antigo valor IFS
para dividir $var
.
Cobri todos os tipos de comandos, mas há mais um caso: quando não há comando para executar , ou seja, se o comando consistir apenas em atribuições (e possivelmente redirecionamentos). Nesse caso, a atribuição permanece em vigor . VAR=VALUE OTHERVAR=OTHERVALUE
é equivalente a VAR=VALUE; OTHERVAR=OTHERVALUE
. Então, depois que IFS=. arr=($var)
, IFS
permanece definido como .
. Como você pode usar $IFS
na atribuição a arr
com a expectativa de que já tenha seu novo valor, faz sentido que o novo valor de IFS
seja usado para a expansão de $var
.
Em resumo, você pode usar apenas IFS
para a divisão de campo temporária :
- iniciando um novo shell ou um subshell (por exemplo,
third=$(IFS=.; set -f; set -- $var; echo "$3")
é uma maneira complicada de fazerthird=${var#*.*.}
, exceto que eles se comportam de maneira diferente quando o valor devar
contém menos de dois.
caracteres); > - em ksh, com
IFS=. some-function
em quesome-function
é definido com a sintaxe kshfunction some-function …
; - no bash e zsh, com
IFS=. some-function
, desde que estejam operando no modo nativo, em oposição ao modo de compatibilidade.