Em um script de shell, se eu definir uma variável como FOO=25, existe uma diferença entre referenciá-la como $FOO$e ${FOO}$?
Em um script de shell, se eu definir uma variável como FOO=25, existe uma diferença entre referenciá-la como $FOO$e ${FOO}$?
Respostas:
Na maioria das situações, tanto $vare ${var}são os mesmos. (Observe 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
será exibido hello.
Para responder à sua pergunta principal, ${foo}é chamado de "expansão de parâmetros" . Para ser mais preciso, o $próprio inicia a expansão do parâmetro, na { }verdade é opcional de acordo com a especificação POSIX , 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, $fooe ${foo}são idênticos. Além de casos como o descrito acima ou quando você está manipulando strings , eles são completamente equivalentes.
No entanto, você realmente não deve usar nenhum deles. A regra geral é que, com muito poucas exceções, você deve sempre usar "$foo"or "${foo}"e never $fooor ${foo}. Você deve sempre citar suas variáveis para evitar chamar o operador split + glob (mais sobre isso mais tarde). Você certamente não quer $foo$. A final $é irrelevante:
$ foo="bar"
$ echo "$foo$"
bar$
Portanto, embora as variáveis não citadas às vezes sejam OK:
$ echo $foo
bar
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 $fooou ${foo}, o shell divide o valor salvo na variável no espaço em branco (isso pode ser alterado definindo a IFSvariável para outra coisa) em uma lista e, em seguida, cada elemento da lista é tratado como um padrão global e expandido para quaisquer arquivos ou diretórios correspondentes. Isso é conhecido como 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 fooe *e, uma vez que *é um curinga que corresponde a qualquer cadeia, o shell diz 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 em rmvez disso echo.
Então, primeira regra: sempre cite suas variáveis. Você pode usar um "$foo"ou outro, "${foo}"mas citá-lo de qualquer maneira. Para obter mais detalhes sobre o uso de variáveis com segurança, consulte estas postagens:
$ var="foo *"ser $ foo="foo *"? Você não usa em varlugar algum.
$no final! Será tratado como caractere normal e não como parte do nome da variável.