eval vs. pipe através do bash

6

Qual é a diferença entre usar:

eval 'echo "foo"'

e

echo 'echo "foo"' | bash

existe algum?

    
por Alexander Mills 07.05.2018 / 06:17

1 resposta

20

Resposta curta

O comando executado por eval é executado no shell atual e o comando canalizado para bash é executado em um sub-shell, por exemplo:

> echo 'x=42' | bash; echo $x

> eval 'x=42'; echo $x
42

Resposta mais longa

Nos comentários foi feita a alegação de que nas versões mais recentes de bash (> = 4,2) o primeiro comando também poderia ter o mesmo efeito. No entanto, este não parece ser o caso.

Na verdade, existem alguns fatores que fazem com que o comando canalizado não seja executado na sessão atual: o pipe e o comando bash .

Na maior parte, os comandos canalizados são executados em subshells. O manual do bash ( seção 3.2.2: pipelines ) tem o seguinte para dizer:

Each command in a pipeline is executed in its own subshell (see Command Execution Environment).

Como apontado nos comentários, esse comportamento pode ser modificado por meio da opção lastpipe . O Manual do Bash ( Seção 4.3.2: O Shopt Builtin ) o seguinte para falar sobre a opção lastpipe :

lastpipe

If set, and job control is not active, the shell runs the last command of a pipeline not executed in the background in the current shell environment.

Podemos verificar que este é o caso da seguinte forma:

Primeiro, ative o lastpipe :

> shopt -s lastpipe

Em seguida, desabilite o controle de trabalho:

> set +m

Agora, execute um comando que defina uma variável dentro de um canal:

> unset x
> echo x=42 | while IFS= read -r line; do eval "${line}"; done;
> echo $x
42

Observe que usamos o comando while e read como solução alternativa, pois o comando eval não pode ler sua entrada de stdin (portanto, não é possível obter sua entrada de um canal).

Este exemplo demonstra que o comando mais à direita no pipe pode, de fato, ser executado no shell atual. No entanto, isso não afeta realmente nosso exemplo original. Mesmo com lastpipe habilitado e controle de trabalho desabilitado, ainda obtemos o seguinte resultado ao canalizar para bash :

> echo 'x=42' | bash; echo $x

>

Isso ocorre porque o próprio comando bash executa sua entrada em um subshell.

    
por 07.05.2018 / 06:35