Por que não é necessário colocar aspas duplas '$ bar' na atribuição 'foo = $ bar'? [duplicado]

2

De link

The main places where it's safe not to use the double quotes are:

  • in an assignment: foo=$bar (but note that you do need the double quotes in export "foo=$bar" or in array assignments like array=("$a" "$b"));
  1. Isso significa que não é necessário duplicar aspas $bar na atribuição foo=$bar ? Por quê?

  2. Por que precisamos das aspas duplas em export "foo=$bar" e em atribuições de matriz como array=("$a" "$b") ?

Obrigado.

    
por Tim 03.08.2017 / 20:55

2 respostas

6
foo=$bar

é seguro porque é uma atribuição , e uma atribuição a uma variável escalar, usando a sintaxe de atribuição escalar. É um contexto escalar , somente um valor pode ser armazenado em $var , não faria sentido dividir ou glob $bar . Se a expansão resultasse em várias palavras, o shell precisaria de alguma forma combiná-las novamente para poder armazená-las como uma string em $foo .

É diferente quando você usa:

foo=($bar)

Onde você está atribuindo a uma variável de matriz. Existe um contexto de lista. Você está atribuindo um número de palavras aos elementos da matriz. split + glob ocorre.

Tenha também cuidado com a natureza dupla de coisas como export / local / typeset / declare / readonly em algumas conchas (explicado em mais detalhes em Citações são necessárias para atribuição de variável local? )

Você notará que:

foo=$bar

é analisado como uma atribuição enquanto

"foo"=$bar

é apenas uma tentativa de executar o comando foo=content_of_bar (onde o conteúdo da barra está sujeito a split + glob).

Em shells em que export (e outros local / typeset ...) é tanto uma palavra-chave quanto uma versão interna (ksh, bash e versões recentes do zsh), em:

export foo=$bar

export é reconhecido como uma palavra-chave e foo=$bar como uma atribuição, portanto $bar não está sujeito a divisão + glob. Mas é preciso pouco para que export pare de ser reconhecido como uma palavra-chave . Nesse caso, ele é tratado apenas como um comando simples e split + glob acontece como em qualquer argumento para qualquer outro comando.

E mesmo nos casos em que export é visto como uma palavra-chave, se os argumentos não se parecem com atribuições de variáveis (como no "foo"=$bar acima), eles são tratados como argumentos normais e sujeitos a divisão + glob novamente.

    
por 03.08.2017 / 22:20
3

Para responder às suas duas perguntas, primeiro precisamos saber o que significa "ser seguro". Bash tem uma infinidade de expansões e todas acontecem em uma certa ordem. Normalmente, quando dizemos que algo é "seguro", queremos dizer que nenhuma divisão involuntária de palavras acontece. Nesse sentido:

  1. é "seguro", ou seja, não são necessárias aspas duplas. Para citar o manual da bash:

    A variable may be assigned to by a statement of the form

              name=[value]
    

    If value is not given, the variable is assigned the null string. All values undergo tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, and quote removal (see EXPANSION below).

    Observe que a divisão de palavras não é executada! Então, a esse respeito, é razoavelmente seguro e executar bar="rm asdf"; foo=$bar; não resultará em nada louco, como falha na execução ou até mesmo o arquivo ser excluído, como $foo ou eval $foo faria. No entanto, o que irá acontecer é a expansão da variável:

    foo="Tomatoes are $50" resultará em foo com o conteúdo Tomatoes are 0 . Isso pode ou não ser o que você queria.

  2. funciona de maneira semelhante: foo="rm asdf"; export bar=$foo não removerá seu arquivo e será analisado corretamente, e foo="rm asdf"; array=($foo) será analisado também. Observe que, no caso da matriz, a divisão de palavras, na verdade, ocorre , portanto, o primeiro elemento de array será rm .

    Além disso, você ainda terá a outra expansão em ambos. Também tenho certeza que a divisão de palavras acontece no caso export , é apenas que as exportações aceitam todas as palavras como argumentos e as analisa da maneira que você espera, da mesma forma como echo $foo não precisa de citações.

Fora de tudo isso, eu chamaria o exemplo de array o menos seguro, porque a divisão de palavras acontece e tem um efeito concreto. Portanto, você precisará de aspas duplas neste caso.

    
por 03.08.2017 / 21:46