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 devarcontém menos de dois.caracteres); > - em ksh, com
IFS=. some-functionem 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.