Qual é a diferença de definir uma variável com ou sem aspas? [duplicado]

3

Se eu definir uma variável com aspas:

TEMP="~/Dropbox"

então

ls $TEMP

não funcionaria, em vez

echo $TEMP | ls

funciona.

E para obter o mesmo resultado, também posso definir a variável sem as aspas, como:

TEMP=~/Dropbox

ao fazer isso, posso simplesmente digitar

ls $TEMP

Estou bastante confuso sobre a diferença entre eles, e estou querendo saber quando e onde devo usar esses dois tipos de definições, respectivamente?

    
por username123 12.07.2015 / 00:55

3 respostas

8
TEMP="~/Dropbox"

O acima define uma variável que contém um til literal seguido por uma barra. Por estar entre aspas, o shell não expande ~/ para o diretório inicial. Observe:

$ echo "quotes=~/" noquotes=~/
quotes=~/ noquotes=/home/john1024/

Assim, se você quiser que ~/ signifique o diretório inicial, então ~/ precisa estar fora das cotas. Os seguintes trabalhos:

TEMP=~/"Dropbox"

Vamos considerar o que acontece se o ~/ estiver entre aspas:

TEMP="~/Dropbox"
ls $TEMP

O comando acima procurará o arquivo ~/Dropbox , o que significa um arquivo chamado Dropbox em um diretório chamado ~ . Como você provavelmente não tem um diretório chamado ~ , ls retornará com uma mensagem de erro: "Nenhum arquivo ou diretório".

Além disso, o comando abaixo não faz o que você pensa:

echo $TEMP | ls

ls ignora a entrada padrão. Um comando ls simples apenas lista os arquivos no diretório atual, seja qual for o diretório.

    
por 12.07.2015 / 01:24
3

man bash e procure por "Tilde Expansion"

ou em resumo: um til sem aspas (~) é substituído pela home do usuário, o que não acontece mais, se for parte de uma variável.

$ T=~/Downloads
$ echo $T
/home/zstegi/Downloads

$ T="~/Downloads"
$ echo $T
~/Downloads
    
por 12.07.2015 / 01:24
3

Existem vários aspectos para esta questão, conforme solicitado. Em primeiro lugar, os efeitos de uma atribuição entre aspas podem diferir da mesma declaração de atribuição sem citações por dois motivos:

  1. Se a atribuição contiver símbolos de sintaxe (como ;<> ou espaço em branco) , as cotações servirão para incluí-las, enquanto a instrução de atribuição sem aspas delimitará no token.

    • Em bash e alguns outros shells, os tokens () são casos especiais em que var=(...) serve para indicar uma atribuição de matriz, embora a mesma construção seja um erro de sintaxe sem aspas em um shell POSIX que não suporta a extensão da matriz.

      (   spc=  sc=; echo "<$spc>:<$sc>"
          spc=' ' sc=\;; echo "<$spc>:<$sc>"
      )
      
      <>:<>
      < >:<;>
      
  2. Se a atribuição contiver tokens de expansão, as cotações podem servir para impedir que a expansão ocorra, como de outra forma aconteceria sem elas.

    • Quaisquer tokens contidos dentro de uma expansão não se aplicam, pois o conteúdo da expansão é literalmente passado da expansão para a variável designada.
    • O " de aspas duplas não atende a esse propósito para $ denotadas expansões de shell e, portanto, é geralmente estranho em uma instrução de atribuição, embora possa ser usado para conter $ denotadas expansões e outros tokens de shell em um contexto citado.

      (   spc=\  sc=";" 
          tkns=$(printf "(<\n\'\t)>|")$spc$sc\"
          names=tkns$spc$"sc$spc$"spc
          printf ::$%s::\n "$names" "$tkns"
      )
      
      ::$tkns $sc $spc::
      ::$(<
      \'  )>| ;"::
      

Os tokens de shell são caracteres muito especiais para o shell - eles são os caracteres que separam os comandos uns dos outros e as palavras de comando dos argumentos de comando. Eles são os caracteres que delimitam / concatenam palavras de shell. Tokens de shell são os caracteres que o sintetizador da shell (ou lexer ) estará procurando e atuando conforme lê em um comando antes de qualquer o shell tem a chance de considerar expandir qualquer parte dele.

Mas há outros caracteres que são quase especiais para o shell. Esses são caracteres que afetam as expansões do shell, como aquelas contidas no valor do parâmetro $IFS do shell, e metacaracteres de expansão de nome de arquivo como ?[* e - como observado em sua pergunta - o ~ tilde.

Com exceção do ~ til em casos especiais, esses caracteres não têm relação com instruções de atribuição - o contexto atribuição (em oposição ao contexto lista ) é imune a ambas as expansões $IFS splitting e filename. E assim, as expansões que ocorrem dentro de uma atribuição de variáveis não precisam ser protegidas para valores literais da maneira que você deveria em uma lista de comandos.

E os seguintes trabalhos ...

(meta=*?; meta=[$meta; echo "$meta")
[*?

O ~ tilde, no entanto, é um tipo especial de expansão de shell. Sua expansão é tratada como um shell alias em que seu conteúdo é sempre expandido literalmente. ~ til e alias expansões - como as mais típicas $ sinal de dólar denotam expansões no contexto atribuição - são sempre imunes a $IFS e nome do arquivo expansões. Eles diferem, entretanto, em que o ~ tilde quase sempre é expandido como argumento, e um shell alias não pode ser expandido nesse contexto a menos que ele siga imediatamente outro alias que foi expandido e cujo valor termina com um < espaço >.

Uma expansão ~ tilde não ocorrerá entre aspas de qualquer tipo e, por falar nisso, não ocorrerá a menos que seja adequadamente delimitada por todos os lados, ou a menos que seu contexto à direita nomeie um usuário do sistema e o shell pode confirmar corretamente este fato.

E então ...

~some_user

... expandirá para o diretório home do usuário some_user se o shell puder confirmar que esse usuário existe ou não expandirá.

Para delimitar adequadamente uma expansão ~ tilde você pode usar qualquer um dos tokens de shell já mencionados exceto as aspas mais um / no lado direito em uma lista contexto, ou, em um contexto atribuição , / ou : no lado direito ou, à esquerda, o primeiro = no comando de atribuição ou : em qualquer outro lugar.

Quando não houver nenhum contexto à direita, e o ~ til for adequadamente delimitado, o ~ tilde será expandido para o valor atual da variável $HOME da shell. Essa distinção é muitas vezes erroneamente ignorada quando se discute a expansão ~ til. O diretório inicial de um usuário e o valor em $HOME não precisam ser os mesmos, pois a variável de shell $HOME pode ser reatribuída ou unset a qualquer momento, como qualquer outro. De fato, quando $HOME é unset , POSIX deixa o comportamento de uma expansão% de% til% solitária, não especificada , embora ~ , por exemplo, tente uma pesquisa com o sistema para o diretório inicial do usuário atual.

Por exemplo:

   
HOME="

:~"::~//~ bash -c '
    printf "\t<%s>" ~/ ~mikeserv/
    HOME=; echo
    printf "\t<%s>" ~/ ~mikeserv/
    unset HOME; echo
    printf "\t<%s>" ~/ ~mikeserv/
'
    <

:~::/home/mikeserv//~/> </home/mikeserv/>
    </> </home/mikeserv/>
    </home/mikeserv/>   </home/mikeserv/>
    
por 12.07.2015 / 07:54