eval vs. pipe through bash (Português)

Qual é a diferença entre usar:

eval "echo "foo"" 

e

echo "echo "foo"" | bash 

existe algum?

Comentários

  • Aqui ' s outra variação com comportamento ligeiramente diferente quanto aos ambientes de execução: ( eval 'echo "foo"' )

Resposta

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 em versões mais recentes de bash (> = 4.2) o primeiro comando também pode 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 canal e o bash command.

Na maior parte, os comandos canalizados são executados em subshells. O manual Bash ( Seção 3.2.2: Pipelines ) tem o seguinte a dizer:

Cada comando em um pipeline é executado em seu próprio subshell (consulte Ambiente de execução de comandos ).

Conforme 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 integrado ) tem o seguinte a dizer sobre a opção lastpipe:

lastpipe

Se definido e o controle de trabalho não estiver ativo, o shell executa o último comando de um pipeline não executado no segundo plano no ambiente shell atual.

Podemos verificar se este é o caso da seguinte maneira.

Primeiro, habilite lastpipe:

> shopt -s lastpipe 

Em seguida, desative o controle de tarefa:

> set +m 

Agora execute um comando que define uma variável de dentro de um tubo:

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

Observe que usamos o while loop e comando read como uma solução alternativa uma vez que o comando eval não pode ler sua entrada de stdin (portanto, não pode obter sua entrada de um tubo).

Este exemplo demonstra que o comando mais à direita no tubo pode, de fato , ser executado no shell atual. No entanto, isso não afeta realmente nosso exemplo original. Mesmo com lastpipe ativado e o controle de trabalho desativado, 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.

Comentários

  • essa é uma boa observação, não ' não percebi isso, mas sim, acho que ' s como os tubos funcionam
  • Apenas curioso, qual é a razão pela qual você não aceitou a resposta?
  • Para bash 4.2+ ao executar um script (ou mais exatamente quando o jobcontrol está desligado) e shopt lastpipe está definido e o pipeline não está em segundo plano, ele executa a extremidade direita do tubo na ' parte superior ' shell não é um subshell. Consulte unix.stackexchange.com/questions/9954/… e unix.stackexchange.com/questions/136206/readarray-or-pipe-issue
  • @ dave_thompson_085 O comando bash pode ser executado em o shell superior dependendo das opções, mas x=42 certamente será executado em algo que pode ser razoavelmente chamado de subshell.
  • @AlexanderMills Na verdade, o pipe não é ' o único problema. O comando bash executará sua entrada em um subshell, independentemente de haver ou não um pipe envolvido. Veja a atualização da minha solução para mais detalhes.

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *