As cotações são necessárias para atribuição de variável local?

28

Posso omitir com segurança as cotações do lado direito de uma tarefa local?

function foo {
    local myvar=${bar}
    stuff()
}

Estou interessado principalmente em bash , mas qualquer informação sobre casos de canto em outras camadas é bem-vinda.

    
por rahmu 25.10.2013 / 15:17

2 respostas

32

As cotações são necessárias em export foo="$var" ou local foo="$var" (ou readonly , typeset , declare e outras variáveis declarando comandos ) em:

  • dash
  • o sh do NetBSD (também baseado no shell Almquist).
  • O sh do FreeBSD 9.2 ou anterior (consulte a alteração em 9.3 )
  • yash
  • zsh com versões anteriores à 5.1 em bash ou sh emulação (ou para export var="$(cmd)" em que zsh executaria a divisão de palavras de outra forma (não globbing)).

Caso contrário, a expansão da variável estaria sujeita à divisão de palavras e / ou geração de nome de arquivo, como em qualquer argumento, a qualquer outro comando.

E não são necessários em bash ou ksh ou sh do FreeBSD 9.3 ou mais recente (onde o comando é analisado de alguma forma como algum tipo de atribuição) nem zsh (onde a divisão de palavras e geração de nome de arquivo é não feito implicitamente na expansão da variável).

Eles são necessários em todos os shell (exceto zsh ), embora em coisas como:

a="b=some value"
export "$a"

De forma mais geral, se algo sobrando do = (incluindo o = ) for citado ou o resultado de alguma expansão (como export 'foo'="$var" , export foo\="$var" ou export foo$((n+=1))="$var" (que $((...)) também deve ser citado na verdade) ...). Ou, em outras palavras, quando o argumento para export não seria uma atribuição de variável válida se fosse escrito sem o export .

Se o nome do comando export / local for citado (mesmo em parte como "export" a="$b" , 'ex'port a="$b" , \export a="$b" ou mesmo ""export a="$b" ), as cotações em torno de $b serão necessárias os casos acima e também em bash , bem como zsh (todas as versões) quando em sh emulação.

Se export / local ou alguma parte dele for o resultado de alguma expansão (como em cmd=export; "$cmd" a="$b" ou mesmo export$(:) a="$b" ) ou se export / local não for a primeira palavra na linha de comando (como em dryrun=; $dryrun export a="$b" ), então as aspas são necessárias em cada shell. No caso de > /dev/null export a="$b" , no entanto, as citações não são necessárias em bash / AT & T ksh e zsh (elas estão em pdksh e derivadas).

Eles não são necessários em nenhum shell quando escritos:

foo=$var export foo

(essa sintaxe sendo também compatível com o shell Bourne, mas no caso de bash e zsh trabalhando somente quando em emulação sh).

(observe que var=value local var não deve ser usado porque o comportamento varia entre os shells).

Tenha também cuidado com este caso especial com bash :

$ bash -c 'IFS=; export a="$*"; echo "$a"' bash a b
ab
$ bash -c 'IFS=; export a=$*; echo "$a"' bash a b
a b

Meu conselho seria sempre citar.

    
por 25.10.2013 / 15:46
2

Eu geralmente cito qualquer uso de variáveis onde possa haver caracteres como espaços em branco. Caso contrário, você terá problemas como este:

#!/bin/bash

bar="hi bye"

function foo {
  local myvar=${bar}
  printf "%s\n" $myvar
  printf "%s\n" "$myvar"
}

foo

O uso da variável em uma atribuição não parece precisar das aspas, mas quando você vai usá-la, como no printf , você precisará citá-la:

  printf "%s\n" "$myvar"

NOTA: Lembre-se de que a variável $IFS é o que determina quais são os caracteres separadores.

IFS    The  Internal  Field  Separator that is used for word splitting after 
       expansion and to split lines into words with the read builtin command. 
       The default value is ''<space><tab><newline>''.

Exemplo

Com a depuração ativada no Bash, podemos ver o que está acontecendo nos bastidores.

$ bash -x cmd.bash 
+ bar='hi bye'
+ foo
+ local 'myvar=hi bye'
+ printf '%s\n' hi bye
hi
bye
+ printf '%s\n' 'hi bye'
hi bye

Acima, podemos ver que a variável $bar foi transferida bem para $myvar , mas quando usamos $myvar , precisávamos ser cognoscentes do conteúdo de $myvar quando íamos use-o.

    
por 25.10.2013 / 15:26