
Wenn ich in einem Shell-Skript eine Variable wie definiere FOO=25
, besteht dann ein Unterschied zwischen der Referenzierung als $FOO$
und ${FOO}$
?
Antwort1
In den meisten Fällen sind $var
und identisch. (Beachten Sie, dass Sie am Ende ${var}
kein „a“ verwenden dürfen !)$
Geschweifte Klammern sind beispielsweise erforderlich, wenn Sie eine Variable in eine fortlaufende Zeichenfolge einfügen müssen.
Beispiel:
var=hel
echo ${var}lo
wird ausgegeben hello
.
Antwort2
Um Ihre Hauptfrage zu beantworten, ${foo}
heißt"Parametererweiterung". Genauer gesagt $
startet die Parametererweiterung selbst, die { }
eigentlich optional sind, gemäßdie POSIX-Spezifikation, kann aber nützlich sein, um das Ende des Variablennamens anzuzeigen:
$ foo="bar"
$ echo $fooBaz ## fails, no variable named $fooBaz exists
$ echo ${foo}Baz ## works, $foo is expanded and the string Baz is appended
barBaz
Im Grunde genommen sind $foo
und ${foo}
identisch. Abgesehen von Fällen wie oben oder wenn SieZeichenfolgenmanipulation, sie sind völlig gleichwertig.
Sie sollten jedoch keines von beiden verwenden. Die Faustregel lautet, dass Sie mit sehr wenigen Ausnahmenstetsverwenden Sie "$foo"
oder "${foo}"
und niemals $foo
oder ${foo}
. Sie sollten Ihre Variablen immer in Anführungszeichen setzen, um den Aufruf des Operators split+glob zu vermeiden (mehr dazu später). Sie möchten sicherlich nicht $foo$
. Das letzte $
ist irrelevant:
$ foo="bar"
$ echo "$foo$"
bar$
Obwohl Variablen ohne Anführungszeichen manchmal in Ordnung sind:
$ echo $foo
bar
Dies ist in der Regel nicht der Fall und sollte unbedingt vermieden werden:
$ 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
Beachten Sie, dass die Klammern auch hier nichts helfen:
$ 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
Wenn Sie $foo
oder verwenden ${foo}
, wird die ShellTeiltder in der Variable gespeicherte Wert bei Leerzeichen (dies kann geändert werden, indem die IFS
Variable auf etwas anderes gesetzt wird) in eine Liste und dann wird jedes Element der Liste als einGlobusMuster und in alle passenden Dateien oder Verzeichnisse erweitert. Dies wird alsteilen+globusOperator. Betrachten Sie zur Veranschaulichung ein Verzeichnis mit zwei Dateien:
$ 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
Lassen Sie uns nun eine Variable auf Folgendes setzen foo *
:
$ foo="foo *"
Was passiert, wenn wir versuchen zu überprüfen, ob eine Datei mit diesem Namen existiert?
$ if [ -e $foo ]; then echo "file exists"; else echo "no such file"; fi
file exists
Die Variable wurde in foo
und aufgeteilt *
. Da *
es sich bei und um ein Platzhalterzeichen handelt, das mit jedem String übereinstimmt, teilt Ihnen die Shell mit, dass eine Datei mit dem Namen foo *
existiert. Wenn wir sie jedoch korrekt zitieren, passiert dies nicht:
$ if [ -e "$foo" ]; then echo "file exists"; else echo "no such file"; fi
no such file
Das war ein triviales Beispiel zur Veranschaulichung. Stellen Sie sich vor, ich hätte rm
statt verwendet echo
.
Also, erste Regel:Setzen Sie Ihre Variablen immer in Anführungszeichen.Sie können entweder "$foo"
oder verwenden "${foo}"
, aber in beiden Fällen müssen Sie es in Anführungszeichen setzen. Weitere Einzelheiten zur sicheren Verwendung von Variablen finden Sie in diesen Beiträgen:
- $VAR vs. ${VAR} und zitieren oder nicht zitieren
- Erweiterung einer Shell-Variable und Auswirkung von Glob und Split darauf
- Sicherheitsimplikationen, wenn vergessen wird, eine Variable in Bash/POSIX-Shells in Anführungszeichen zu setzen
- Warum muss ich die Variable für „if“ in Anführungszeichen setzen, für „echo“ aber nicht?