A idéia básica é que os VAR=VALUE some-commandconjuntos VARpara VALUEa execução de some-commandquando some-commandé um comando externo, e ele não fica mais chique do que isso. Se você combinar essa intuição com algum conhecimento de como um shell funciona, na maioria dos casos, você encontrará a resposta certa. A referência do POSIX é "Comandos simples" no capítulo "Linguagem de comando do shell" .
Se some-commandé um comando externo , VAR=VALUE some-commandé equivalente a env VAR=VALUE some-command. VARé exportado no ambiente de some-commande seu valor (ou falta de valor) no shell não muda.
Se some-commandé uma função , então VAR=VALUE some-commandé equivalente a VAR=VALUE; some-command, ou seja, a atribuição permanece em vigor após o retorno da função e a variável não é exportada para o ambiente. A razão disso tem a ver com o design do shell Bourne (e posteriormente com a compatibilidade com versões anteriores): ele não tinha capacidade para salvar e restaurar valores variáveis em torno da execução de uma função. Não exportar a variável faz sentido, pois 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, onde VARé definido apenas durante a execução da função (também é exportado). No ksh , isso é feito se a função for definida com a sintaxe kshfunction NAME …, não se for definido com a sintaxe padrão NAME (). No bash , isso é feito apenas no modo bash, não no modo POSIX (quando executado com POSIXLY_CORRECT=1). No zsh , isso é feito se a posix_builtinsopção não estiver configurada; esta opção não está definida por padrão, mas está ativada por emulate shou emulate ksh.
Se some-commandfor um builtin, o comportamento depende do tipo de builtin. Construções especiais se comportam como funções. Built-ins especiais são os que precisam ser implementados dentro do shell porque afetam o estado do shell (por exemplo break, cdafeta o fluxo de controle, afeta o diretório atual, setafeta parâmetros e opções posicionais ...). Outros componentes internos são integrados apenas para desempenho e conveniência (principalmente - por exemplo, o recurso bash printf -vpode ser implementado apenas por um componente interno) e se comportam como um comando externo.
A atribuição ocorre após a expansão do alias; portanto, se some-commandfor um alias , expanda-o primeiro para descobrir o que acontece.
Observe que, em todos os casos, a atribuição é executada após a análise da linha de comando, incluindo qualquer substituição de variável na própria linha de comando. Então , var=a; var=b echo $varimprime a, porque $varé avaliado antes da atribuição. E, assim, IFS=. printf "%s\n" $varusa o IFSvalor antigo para dividir $var.
Eu cobri todos os tipos de comandos, mas há mais um caso: quando não há comando para executar , ou seja, se o comando consiste apenas em atribuições (e possivelmente redirecionamentos). Nesse caso, a atribuição permanece no local . VAR=VALUE OTHERVAR=OTHERVALUEé equivalente a VAR=VALUE; OTHERVAR=OTHERVALUE. Então IFS=. arr=($var), depois , IFSpermanece definido como .. Como você pode usar $IFSna atribuição arrcom a expectativa de que ele já tenha seu novo valor, faz sentido que o novo valor de IFSseja usado para a expansão de $var.
Em resumo, você pode usar apenas IFSpara divisão temporária de campos:
- iniciando um novo shell ou um subshell (por exemplo,
third=$(IFS=.; set -f; set -- $var; echo "$3")é uma maneira complicada de fazer, third=${var#*.*.}exceto que eles se comportam de maneira diferente quando o valor de varcontém menos de dois .caracteres);
- em ksh, com
IFS=. some-functiononde some-functioné definido com a sintaxe ksh function some-function …;
- no bash e zsh,
IFS=. some-functiondesde que estejam operando no modo nativo em oposição ao modo de compatibilidade.
IFSpermanece definido como." Eek. Depois de ler a primeira parte, isso faz sentido, mas antes de postar este Q, eu não esperava isso.