As aspas simples e as aspas duplas são manipuladas por “bash” ou por “echo”?

2

Quando você faz algo assim:

echo 'Hello World'

Ou assim:

x=12345
echo "x is: $x"

No primeiro exemplo, o comando echo recebe 'Hello World' , ou recebe Hello World ?

E no segundo exemplo, o comando echo recebe "x is: $x" ou recebe x is: 12345 ?

Então, basicamente, minha pergunta é: Aspas simples e aspas duplas são manipuladas por bash ou echo ?

    
por user267365 24.12.2017 / 16:40

2 respostas

3

Citações, expansão variável, curingas e tudo mais mencionado na seção manual do bash expansão é tratada pelo bash.

Por exemplo, quando você executa o comando bash echo "x is: $x" , o bash analisa isso para descobrir que ele precisa executar o comando echo com um argumento que é x is: 12345 . Dado echo "x is" "$x" , bash executa echo com dois argumentos: x is e 12345 - é por isso que os dois espaços dentro das aspas são preservados (eles fazem parte do argumento que echo imprime não modificado), mas os dois espaços fora das aspas não são (para o shell, dois espaços para separar argumentos são tão bons quanto um único, e echo sempre imprime um único espaço entre eles).

O comando echo (ou qualquer outro comando) não tem como saber qual comando shell produziu o argumento x is: 12345 , ou se um shell estava envolvido. Aqui estão alguns exemplos de comandos que produzem este argumento:

echo "x is: 12345"
echo 'x is: 12345'
echo x\ is:\ 12345
echo "x is: $x"
echo 'x is:'\ "$x"
echo "$(echo "x ")is: $x"
# Assume there is no other file whose name begins with x in the current directory
touch "x is: $x"; echo x*

Ou pode ser exec "echo", "x is: 12345" em Perl ou execlp("echo", "echo", "x is: 12345") em C, etc.

Isso vale para todos os comandos. E o mesmo princípio vale para outras conchas, embora cada uma tenha um conjunto de expansões ligeiramente (ou significativamente) diferente.

Por outro lado, opções são manipuladas pelo comando. Por exemplo, ls -l -t e ls -l "-t" no bash (ou qualquer shell semelhante) executam ls exatamente da mesma maneira, com os dois argumentos -l e -t . É por isso que nenhuma forma de cotação de shell ajudará você se desejar executar ls para exibir informações sobre um arquivo chamado -t . Você pode fazer isso com ls -l -- -t , ou seja, passando -- como argumento. Esta é uma convenção seguida pela maioria dos comandos: nada depois de -- é analisado como uma opção. Mais uma vez, esta é uma característica do comando; para o shell, um traço principal não é nada especial.

Uma coisa que pode ficar complicada são as barras invertidas. No bash e em outros shells, a barra invertida fora de qualquer citação significa que o próximo caractere perde seu significado especial. Por exemplo, echo \"x\ is:\ 12345\" imprime "x is: 12345" , porque cada um dos caracteres precedidos por uma barra invertida perde seu significado especial (sintaxe de cotação para " , separador de palavras para espaços). Mas alguns comandos também interpretam barras invertidas. Quando isso acontecer, você precisa garantir que a barra invertida chegue até eles. Por exemplo, no bash, o comando echo imprime barras invertidas literalmente por padrão, mas se você passar a opção -e ou executar shopt xpg_echo primeiro, então echo terá suas próprias seqüências de escape (isso é para bash, o% O comandoecho em shells diferentes e em sistemas diferentes tem regras diferentes sobre se eles tratam as barras invertidas especialmente). Por exemplo, echo 'a\nb' imprime a\nb , enquanto echo -e 'a\nb' imprime a -newline- b porque \n significa “nova linha” para echo -e . Por outro lado, echo a\nb imprime anb , pois \n é expandido pelo shell e há \ significa "citar o próximo caractere".

Além disso, tenha cuidado quando vários invólucros estiverem envolvidos, por exemplo, com SSH. Quando você executa ssh em um shell, o shell local analisa o comando como de costume. O cliente SSH une seus argumentos de não opção com espaços no meio e envia a sequência resultante para o servidor SSH. O servidor SSH passa essa string para o shell remoto. Isso significa que existem duas rodadas completas de expansão de shell entre o que você digita em um terminal ou em um shell script e o que é executado na máquina remota.

    
por 24.12.2017 / 18:22
0

Nos seus exemplos: as aspas são usadas pelo shell.

O primeiro passo que o shell (todas as shells) leva é para dividir a linha de comando em tokens .

O primeiro passo no Capítulo 7.3: Processamento de linha de comando é dividir. Por favor, também dê uma olhada na "Figura 7.1: Etapas no processamento de linha de comando".

Cada token é uma parte da linha. Cada token pode ser alguma expansão ou outros tokens.

A divisão é feita principalmente em metacaracteres (o espaço é um meta-caractere, o mais comumente usado), as citações modificam a divisão. Aspas simples agrupam todos os caracteres (incluindo espaços) como um token.

Você pode "ver" a divisão com printf:

$ printf '<%s>\n' echo 'Hello World'
<echo>
<Hello World>

As aspas duplas também agrupam os caracteres, mas permitem algumas expansões internas.

$ x=12345
$ echo "x is: $x"
x is: 12345
$ printf '%s' echo "x is: $x"
<echo>
<x is: 12345>

As cotações também podem aparecer como:

$ echo $(printf '"%s" ' "Hello World")
"Hello World"

No entanto, a divisão feita pela casca adiciona uma reviravolta interessante:

$ printf '<%s>\n' echo $(printf '"%s" ' "Hello World")
<echo>
<"Hello>
<World">

A divisão é feita no resultado da expansão de comando. Citando a expansão do comando evita a divisão:

$ printf '<%s>\n' echo "$(printf '"%s" ' "Hello World")"
<echo>
<"Hello World" >

Outra das citações é a barra invertida. Citando o espaço, ele age como um caractere normal (não um metacaractere dividido):

$ printf '<%s>\n' echo Hello\ World
<echo>
<Hello World>
    
por 25.12.2017 / 00:26