valor temporário do script bash no comando

8

Como abaixo do comando,

if true; then
   IFS=":" read a b c d e f <<< "$test"

O livro diz que quando o comando de atribuição de valor ( IFS ":" ) é usado antes do comando principal ( read a b c d e f <<< "$value" ), seu valor é efetivo temporariamente no comando principal. Portanto, o comando read usa o delimitador : .

Mas, como este comando,

if true; then
   HOME="hello" echo "$HOME"

A mensagem de eco não é alo. Qual é o significado real do comando acima?

    
por A.Cho 28.02.2016 / 15:31

3 respostas

5

Isso se resume a uma questão de como a avaliação funciona. Os dois exemplos funcionam da mesma maneira, o problema acontece porque o shell (bash, aqui) expande as variáveis.

Quando você escreve este comando:

HOME="foo" echo $HOME

O $HOME é expandido antes do comando ser executado . Portanto, ele é expandido para o valor original e não para o novo que você definiu para o comando. A variável HOME foi realmente alterada no ambiente em que o comando echo está sendo executado, no entanto, você está imprimindo o $HOME do pai.

Para ilustrar, considere isto:

$ HOME="foo" bash -c 'echo $HOME'
foo
$ echo $HOME
/home/terdon

Como você pode ver acima, o primeiro comando imprime o valor temporariamente alterado de HOME e o segundo imprime o original, demonstrando que a variável foi alterada apenas temporariamente. Como o comando bash -c ... está entre aspas simples ( ' ' ) em vez das duplas ( " " ), a variável não é expandida e é passada como está para o novo processo bash. Esse novo processo, em seguida, expande e imprime o novo valor para o qual foi definido. Você pode ver isso acontecer se você usar set -x :

$ set -x
$ HOME="hello" echo "$HOME"
+ HOME=hello         
+ echo hello
hello

Como você pode ver acima, a variável $HOME nunca é passada para echo . Só vê seu valor expandido. Compare com:

$ HOME="hello" bash -c 'echo $HOME'
+ HOME=hello
+ bash -c 'echo $HOME'
hello

Aqui, por causa das aspas simples, a variável e não seu valor são passados para o novo processo.

    
por 28.02.2016 / 16:28
7

Quando o shell estiver analisando uma linha, ele transformará a linha em palavras, várias expansões (em ordem) nas palavras, então execute o comando.

Suponha que test=1:2:3:4:5:6

Vamos ver este comando: IFS=":" read a b c d e f <<< "$test"

Após o tokenizing e a expansão do parâmetro ocorre: IFS=":" read a b c d e f <<< "1:2:3:4:5:6"

O shell configurará a variável IFS para a duração do comando read e read saberá como aplicar o $ IFS à sua entrada e fornecer valores aos nomes das variáveis.

Este comando tem uma história semelhante, mas resultado diferente: HOME="hello" echo "$HOME"

Como a expansão do parâmetro acontece antes do início do comando, o shell tem:

HOME="hello" echo "/home/username"

E então, durante a execução do comando echo, o novo valor de $ HOME não é usado.

Para conseguir o que você está tentando fazer, escolha um dos

# Delay expansion of the variable until its new value is set
HOME="hello" eval 'echo "$HOME"'

ou

# Using a subshell, so the altered env variable does not affect the parent.
# The semicolon means that the variable assignment will occur before
# the variable expansion
(HOME="hello"; echo "$HOME")

mas não escolha o primeiro.

    
por 28.02.2016 / 16:29
-1

Existem dois escopos: variáveis de ambiente e variáveis locais. As variáveis de ambiente são válidas para cada processo (consulte setenv , getenv ), enquanto as variáveis locais estão ativas apenas nessa sessão de shell. (Não é uma distinção óbvia ...)

env implícita (como no seu exemplo) modifica o ambiente, enquanto echo ... usa os locais - por isso env não tem efeito.

Para modificar as variáveis locais, use, digamos,

( HOME="foo" ; echo "$HOME" )

Aqui os parênteses definem o escopo desta atribuição.

    
por 28.02.2016 / 15:43