Referenciando variáveis em um script de shell

8

Em um script de shell, se eu definir uma variável como FOO=25 , há uma diferença entre referenciá-lo como $FOO$ e ${FOO}$ ?

    
por Karnivaurus 09.10.2015 / 12:55

2 respostas

15

Na maioria das situações, $var e ${var} são iguais. (Note que você não deve usar um $ no final!)

Um exemplo em que você precisa de chaves é quando você precisa colocar uma variável em uma sequência contínua.

Exemplo:

var=hel
echo ${var}lo

produzirá hello .

    
por Aizuddin Zali 09.10.2015 / 13:09
11

Para responder à sua pergunta principal, ${foo} é chamado de "expansão de parâmetro" . Para ser preciso, o $ inicia a expansão do parâmetro, os { } são realmente opcionais de acordo com o POSIX especificação , mas pode ser útil para indicar o final do nome da variável:

$ foo="bar"
$ echo $fooBaz   ## fails, no variable named $fooBaz exists

$ echo ${foo}Baz ## works, $foo is expanded and the string Baz is appended
barBaz

Basicamente, $foo e ${foo} são idênticos. Além de casos como o acima ou quando você está fazendo manipulação de string , eles são completamente equivalentes .

No entanto, você não deve usar nenhum deles. A regra básica é que, com pouquíssimas exceções, você deve sempre usar "$foo" ou "${foo}" e nunca $foo ou ${foo} . Você deve sempre citar suas variáveis para evitar invocar o operador split + glob (mais sobre isso depois). Você certamente não deseja $foo$ . O% final $ é irrelevante:

$ foo="bar"
$ echo "$foo$"
bar$

Assim, enquanto as variáveis sem aspas são às vezes OK:

$ echo $foo
bar

Eles geralmente não são e devem ser realmente evitados:

$ if [ -n $foo ]; then echo empty; else echo "not empty"; fi ## fails
empty

$ if [ -n "$foo" ]; then echo empty; else echo "not empty"; fi ## works
not empty

Observe que os colchetes também não ajudam aqui:

$ if [ -n ${foo} ]; then echo empty; else echo "not empty"; fi  ## fails
empty

$ if [ -n "${foo}" ]; then echo empty; else echo "not empty"; fi ## works
not empty

Quando você usa $foo ou ${foo} , o shell divide o valor salvo na variável no espaço em branco (isso pode ser alterado definindo a variável IFS para outra coisa) em uma lista e, em seguida, cada elemento da lista é tratado como um padrão glob e expandido em quaisquer arquivos ou diretórios correspondentes. Isso é conhecido como o operador split + glob . Para ilustrar, considere um diretório com dois arquivos:

$ ls -l
-rw-r--r-- 1 terdon terdon 0 Oct  9 18:16 file1
-rw-r--r-- 1 terdon terdon 0 Oct  9 18:16 file2

Agora, vamos definir uma variável para foo * :

$ foo="foo *"

O que acontece se tentarmos verificar se existe um arquivo com esse nome?

$ if [ -e $foo ]; then echo "file exists"; else echo "no such file"; fi
file exists

A variável foi dividida em foo e * e, como * é um curinga que corresponde a qualquer sequência, o shell informa que um arquivo chamado foo * exxists. No entanto, se citá-lo corretamente, isso não acontece:

$ if [ -e "$foo" ]; then echo "file exists"; else echo "no such file"; fi
no such file

Esse foi um exemplo trivial para ilustrar o ponto. Imagine se eu tivesse usado rm em vez de echo .

Então, primeira regra: sempre cite suas variáveis. Você pode usar "$foo" ou "${foo}" , mas citar de qualquer forma. Para mais detalhes sobre o uso de variáveis com segurança, dê uma olhada nestes posts:

por terdon 09.10.2015 / 17:12