Em $(echo "echo 'a'; echo 'b'")
, o shell vê uma substituição de comando. E é isso. Então, esse será um comando simples cujos argumentos são resultantes do operador split + glob na expansão da substituição do comando.
O shell pegará a saída do comando echo "echo 'a'; echo 'b'"
, nesse caso echo 'a'; echo 'b'\n
, removerá os caracteres de nova linha à direita para que se torne echo 'a'; echo 'b'
, divida isso de acordo com o valor da variável $IFS
.
Se $IFS
não tiver sido alterado de seu padrão, serão 4 palavras: echo
, 'a';
, echo
e 'b'
. Cada uma dessas palavras estará sujeita a globbing. Aqui, nenhum contém caracteres globbing, então essas palavras permanecerão como estão.
Portanto, temos 4 argumentos para executar um comando simples. O primeiro argumento será usado para derivar o comando a ser executado. echo
está embutido na maioria dos shells. Portanto, o shell chamará seu echo
integrado com esses 4 argumentos.
echo
ignora seu primeiro (0º) argumento e exibe os outros separados por caracteres de espaço e finalizados por um caractere de nova linha. Algumas implementações de echo
expandem sequências de escape de barra invertida, mas não há nenhuma aqui. Então, echo
irá produzir:
'a'; echo 'b'\n
Se você quiser avaliar, ou seja, se quiser que a string seja interpretada como código de shell, use eval
:
eval "echo 'a'; echo 'b'"
Isso também é reconhecido como um comando simples. Por causa das cotações, o shell vê duas "palavras": eval
e echo 'a'; echo 'b'
. Novamente, eles comporão os argumentos para o comando que é derivado do primeiro.
Aqui o comando é o comando eval
builtin do shell. Novamente, eval
ignora seu primeiro argumento. O que ele faz é concatenar seus outros argumentos (aqui há apenas um) com espaços e interpretar a string resultante como código shell. Ao interpretar
echo 'a'; echo 'b'
O shell vê um ;
sem aspas, que delimita os comandos. O primeiro é tratado como um comando simples que acaba chamando echo
com dois argumentos ... etc.