Riferimenti a variabili in uno script di shell


10

In uno script di shell, se definisco una variabile come FOO=25, c'è una differenza tra il riferimento a come $FOO$e ${FOO}$?


2
Alla fine non devi usare il $! Verrà trattato come un carattere normale e non come parte del nome della variabile.
Byte Commander

Risposte:


16

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.


11

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:


Non volevo modificare la risposta altrimenti eccellente, ma non dovrebbe $ var="foo *"essere $ foo="foo *"? Non usi da varnessuna parte.
Joe,

@Joe oh, buon dolore! Sì, certo che dovrebbe, grazie per averlo sottolineato. A proposito, sentiti libero di correggere tali errori suggerendo una modifica. Questo genere di cose è molto incoraggiato, proprio per evitare sciocchi errori come questo.
terdon,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.