Encapsulamento do comando Backtick

2
test@debian:~$ echo 'echo \'echo "uh!"\''
uh!

Como o Bash faz isso? Parece que ele primeiro executa a expressão nos backticks não-escapados, o que retorna (as aspas duplas "" são removidas, certo?):

'echo uh!'

Portanto, temos uma entrada equivalente a:

test@debian:~$ echo 'echo uh!'

(nota lateral: realmente, por que funciona? Porque:

test@debian:~$ echo 'echo uh!'
-bash: !': event not found

)

Em seguida, o Bash executa a expressão em backticks novamente, o que dá:

test@debian:~$ echo uh!

Que finalmente nos dá a saída:

uh!

Isso é certo? E como se poderia encapsular quatro echo -backtick-expression entre si?

    
por wolf-revo-cats 18.01.2016 / 17:19

2 respostas

6

Depende da sua versão de bash :

bash-4.2$ echo 'echo \'echo "uh!"\''
bash: !"\'': event not found
bash-4.3$ echo 'echo \'echo "uh!"\''
uh!

Em bash-4.3 , !" não é mais elegível como designador de evento histórico, portanto, a expansão do histórico não se aplica.

Além disso, é apenas uma sintaxe de aninhamento backtick normal. Dentro dos backticks, o caractere de barra invertida é sobrecarregado (mais uma vez) para fazer essa expansão aninhada novamente.

Você pode aninhar quantos níveis desejar:

echo 'echo \'echo \\'echo \\\\'echo whatever\\\\'\\'\''

Qual é o equivalente pesado de:

echo $(echo $(echo $(echo $(echo whatever))))

No entanto, note que em ambas as versões, a substituição de comandos está sujeita à divisão de palavras. Então, você gostaria de citá-los para evitar isso.

Com bash , dash , pdksh , yash , zsh , é relativamente fácil:

echo "'echo "\'echo "\\'echo "\\\\'echo whatever\\\\'"\\'"\'"'"

Com o shell Bourne ou Korn, você também precisa escapar do " , então isso se torna:

echo "'echo \"\'echo \\"\\'echo \\\\"\\\\'echo whatever\\\\'\\\\"\\'\\"\'\"'"

Compare com:

echo "$(echo "$(echo "$(echo "$(echo whatever)")")")" 
    
por 18.01.2016 / 18:07
2

Isso é interessante.

Isso se expande para uh:

echo 'echo \'echo uh\''

e nem mesmo

echo "'echo \'echo uh\''"

suprime a expansão interna.

Em ambas as conchas bash e POSIX (traço), você tem $() como uma alternativa amigável para aninhamento de backticks.

Curiosamente, a substituição do processo interno não se expande com $() independentemente de estar entre aspas ou não, ou se a substituição interna usa backticks ou $() :

$ echo $(echo \$\(echo uh\))
  $(echo uh)
$ echo $(echo \'echo uh\')
  'echo uh'

A expansão implícita com backticks não parece muito segura. Eu ficaria com $() , especialmente se você quiser aninhar.

    
por 18.01.2016 / 17:51