Qual é a diferença entre usar:
eval "echo "foo""
e
echo "echo "foo"" | bash
existe algum?
Comentários
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, masx=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.
( eval 'echo "foo"' )