In uno script di shell, se definisco una variabile come FOO=25, c'è una differenza tra il riferimento a come $FOO$e ${FOO}$?
In uno script di shell, se definisco una variabile come FOO=25, c'è una differenza tra il riferimento a come $FOO$e ${FOO}$?
Risposte:
Nella maggior parte dei casi entrambi $vare ${var}sono uguali. (Nota che non devi usare $a alla fine!)
Un esempio in cui sono necessarie parentesi graffe è quando è necessario inserire una variabile in una stringa continua.
Esempio:
var=hel
echo ${var}lo
uscirà hello.
Per rispondere alla tua domanda principale, ${foo}si chiama "espansione dei parametri" . Per essere precisi, lo $stesso avvia l'espansione dei parametri, in { }realtà sono opzionali in base alle specifiche POSIX , ma possono essere utili per indicare la fine del nome della variabile:
$ foo="bar"
$ echo $fooBaz ## fails, no variable named $fooBaz exists
$ echo ${foo}Baz ## works, $foo is expanded and the string Baz is appended
barBaz
Fondamentalmente $fooe ${foo}sono identici. A parte casi come sopra o quando si sta manipolando una stringa , sono completamente equivalenti.
Tuttavia, non dovresti davvero usare nessuno dei due. La regola empirica è che, con pochissime eccezioni, dovresti sempre usare "$foo"o "${foo}"e mai $fooo mai ${foo}. Dovresti sempre citare le tue variabili per evitare di invocare l'operatore split + glob (ne parleremo più avanti). Di certo non vuoi $foo$. Il finale $è irrilevante:
$ foo="bar"
$ echo "$foo$"
bar$
Quindi, mentre le variabili non quotate a volte vanno bene:
$ echo $foo
bar
Di solito non lo sono e dovrebbero davvero essere evitati:
$ 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
Si noti che le parentesi non aiutano neanche qui:
$ 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 usi $fooo ${foo}, la shell dividerà il valore salvato nella variabile su uno spazio bianco (questo può essere cambiato impostando la IFSvariabile su qualcos'altro) in un elenco e quindi, ogni elemento dell'elenco viene trattato come un modello glob ed espanso in qualsiasi file o directory corrispondente. Questo è noto come operatore split + glob . Per illustrare, considera una directory con due file:
$ 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
Ora, impostiamo una variabile su foo *:
$ foo="foo *"
Cosa succede se proviamo a verificare se esiste un file con quel nome?
$ if [ -e $foo ]; then echo "file exists"; else echo "no such file"; fi
file exists
La variabile è stata divisa in fooe *e, poiché *è un carattere jolly che corrisponde a qualsiasi stringa, la shell ti dice che un file chiamato foo *exxist. Tuttavia, se lo citiamo correttamente, ciò non accade:
$ if [ -e "$foo" ]; then echo "file exists"; else echo "no such file"; fi
no such file
Questo è stato un esempio banale per illustrare il punto. Immagina se avessi usato rminvece di echoperò.
Quindi, prima regola: cita sempre le tue variabili. Puoi usare uno "$foo"o l' "${foo}"altro o citarlo in entrambi i modi. Per maggiori dettagli sull'uso sicuro delle variabili, dai un'occhiata a questi post:
$ var="foo *"essere $ foo="foo *"? Non usi da varnessuna parte.
$! Verrà trattato come un carattere normale e non come parte del nome della variabile.