Por que o bash não remove a barra invertida na etapa de remoção de cotação neste exemplo?

0

No bash

$ va='\abc'
$ echo $va
\abc

Na atribuição va='\abc' , as aspas simples preservam as duas barras invertidas no valor de va .

No comando echo echo $va , está correto que o bash primeiro realize a expansão de parâmetros em $va (expanda-o para \abc ) e, em seguida, execute uma remoção de cotação no resultado da expansão de parâmetro? A remoção de cotas remove as barras invertidas e aspas, mas por que as duas barras invertidas ainda são preservadas? Espero que o resultado seja \abc . Para comparação

$ echo \abc
\abc

Eu sinto falta de algo no manual de bash? Eu aprecio que alguém possa apontar o que sinto falta.

Obrigado.

    
por Tim 14.11.2018 / 01:45

3 respostas

5

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.

    
por 14.11.2018 / 02:15
3

Do I miss something in the bash manual?

Sim. Do manual :

After the preceding expansions, all unquoted occurrences of the characters ‘\’, ‘'’, and ‘"’ that did not result from one of the above expansions are removed.

As "expansões precedentes" e "expansões acima" aqui sendo expansão de parâmetro (variável), substituição de comando, etc.

    
por 14.11.2018 / 05:05
-2

A resposta é simples, a linha:

echo $va

não contém aspas que precisam ser removidas.

É assim que o shell foi definido desde mais de 40 anos. Note-se que a Bourne Shell apareceu pela primeira vez AT & T internamente em 1976.

BTW: "citar" a este respeito significava personagens com o oitavo bit nos anos 70. Então isso em uma forma interna de citação de shell.

Como o Bourne Shell foi reformulado para suportar caracteres de 8 bits, em meados dos anos 80, essa forma interna de correspondência foi substituída por barras invertidas nas strings internas antes de qualquer caractere citado.

Hoje, o Bourne Shell funciona da seguinte maneira:

  • As cadeias escritas em aspas simples são substituídas pelo formulário de barra invertida. Este, e. significa que 'abc' é substituído por \ a \ b \ c

  • As strings com barras invertidas explicitamente digitadas são mantidas internamente.

  • As cadeias com aspas duplas mantêm suas aspas duplas, então "abc" permanece internamente "abc"

Ao fazer a expansão de parâmetros, o shell substitui todos os tipos de strings entre aspas (veja três formulários acima) pelo formulário com barras invertidas simples antes de qualquer caractere e isso é o que é removido ao fazer "remoção de cotação".

BTW: a expansão da variável:

abc=123

feito com

command "$abc"

resulta em

command 

antes da remoção da cotação ser concluída.

command $abc

resulta em

command 123

antes da remoção da cotação ser concluída.

    
por 14.11.2018 / 11:46

Tags