Comece com uma comparação mais simples:
$ echo '\abc'
\abc
$ echo \abc
\abc
No primeiro comando, os apóstrofos não se tornam parte do argumento para echo
porque eles foram usados para citar. Todos os caracteres dentro, incluindo as barras invertidas, são passados para echo
.
No segundo comando, a primeira barra invertida cita a segunda barra invertida. O que foi usado para citar não se torna parte do argumento para echo
. O outro é passado para echo
, junto com o abc
(que não foi citado, mas isso não importa, porque eles não são metacaracteres).
Agora estamos prontos para falar sobre sua sequência de comandos
$ va='\abc'
$ echo $va
\abc
Quando o comando de atribuição é executado, os apóstrofos citam tudo entre eles. Os apóstrofos não se tornam parte do valor atribuído, mas todo o resto faz, incluindo as barras invertidas.
No comando echo
, não há caracteres de citação. O valor de va
é recuperado e inserido na lista de argumentos. Agora, há um argumento contendo 2 barras invertidas, mas elas não funcionam como caracteres de citação, porque as fases de análise em que estávamos procurando caracteres de citação eram feitas antes da expansão da variável.
Expansão variável não é como expansão macro. A série resultante de argumentos não é retornada ao analisador de linha de comando completo. Algum pós-processamento é feito (divisão de palavras e globbing), mas não há uma segunda passagem de remoção de cotação e expansão de variável.
Quando você deseja criar uma lista de argumentos e reexaminar tudo como uma nova linha de comando com todos os recursos de shell disponíveis, use eval
. Isso geralmente é uma má idéia porque "todos os recursos do shell" são muito, e se você não for cuidadoso, algo ruim pode acontecer.
$ va='\abc'
$ eval echo $va
\abc
Perfeito, certo?
$ va='\abc;rm -rf $important_database'
$ eval echo $va
\abc
^C^C^C ARGH!
Quando você quiser usar a sintaxe de citação de shell dentro do valor de uma variável de shell, tente pensar em uma maneira diferente de resolver seu problema.