A correção do shell de shell quebrou ferramentas de linha de comando básicas como echo e cat? [duplicado]

5

Eu costumava fazer coisas como:

X=123 cat <<EOF
X is $X
EOF

ou ainda mais simples:

X=123 echo $X

O primeiro ainda parece funcionar no Mac OS X depois de instalar o bash fix, no entanto, nenhum deles parece funcionar na minha instância do Ubuntu 14.04 na AWS. O que faz com que echo ou cat não tenha mais acesso a essas variáveis de ambiente? Ainda mais estranho, quando eu passo o env vars para um aplicativo NodeJS, não pareço ter nenhum problema:

cat <<EOF > test.js
console.log('X is ' + process.env.X);
EOF
X=123 node test.js

Isso parece funcionar também em scripts bash:

cat <<EOF > test.sh
echo X is \$X
EOF
chmod +x test.sh
X=123 ./test.sh
    
por Abdullah Jibaly 08.10.2014 / 00:13

2 respostas

8

Em qualquer shell POSIX, quando você escreve

X=123 echo $X

o $X é expandido antes de todo o comando ser executado, ou seja, se $X estiver inicialmente não definido, você verá:

X=123 echo

que é então executado. Você pode ver mais ou menos o que o shell está fazendo com set -x :

$ set -x
$ X=123 echo X=$X
+ X=123
+ echo X=
X=
$ set +x

Você pode ver que echo (na verdade, o próprio shell, que faz a expansão antes de executar echo ) ainda tem acesso ao ambiente:

$ X=123 eval 'echo $X'
123

O problema com cat <<EOF é semelhante. Note que em relação a bash , havia um bug em versões antigas (anteriores a 4.1), descritas no arquivo CHANGES como:

Fixed a bug that caused variable expansion in here documents to look in any temporary environment.

Esta pode ser a causa do comportamento observado no Mac OS X. Não confie neste bug.

    
por 08.10.2014 / 01:17
6

Suas perguntas sobre os documentos aqui provavelmente não estão relacionadas. O problema é que bash executará as expansões e a atribuição simultaneamente - portanto, um X=123... inicial não deve afetar o valor expandido de dentro do documento here. Isso ocorre porque o documento here é um descritor de arquivo de entrada que bash deve construir e passar para cat na invocação da mesma forma que deve atribuir 123 a $X antes de passar isso mais o restante do ambiente para cat at execve time.

Considere:

X=321; X=123 bash <<HEREDOC
echo "$X is not yet \$X and $$ is not yet \$$."
HEREDOC

OUTPUT

321 is not yet 123 and 17134 is not yet 17225.
    
por 08.10.2014 / 08:13