Referenzieren von Variablen in einem Shell-Skript

10

Wenn ich in einem Shell-Skript eine Variable wie z. B. definiere FOO=25, gibt es einen Unterschied zwischen der Referenzierung als $FOO$und ${FOO}$?

Karnivaurus
quelle
2
Sie dürfen das $am Ende nicht benutzen ! Es wird als normales Zeichen und nicht als Teil des Variablennamens behandelt.
Byte Commander

Antworten:

16

In den meisten Situationen sind beide $varund ${var}gleich. (Beachten Sie, dass Sie $am Ende kein a verwenden dürfen !)

Ein Beispiel, bei dem Sie geschweifte Klammern benötigen, ist, wenn Sie eine Variable in eine fortlaufende Zeichenfolge einfügen müssen.

Beispiel:

var=hel
echo ${var}lo

wird ausgegeben hello.

Aizuddin Zali
quelle
11

Zur Beantwortung Ihrer Hauptfrage ${foo}heißt "Parametererweiterung" . Um genau zu sein, $startet das selbst die Parametererweiterung, die { }gemäß der POSIX-Spezifikation tatsächlich optional sind , aber nützlich sein kann, um das Ende des Variablennamens anzugeben:

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

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

Grundsätzlich $foound ${foo}sind identisch. Abgesehen von Fällen wie den oben genannten oder wenn Sie eine Zeichenfolgenmanipulation durchführen , sind sie völlig gleichwertig.

Sie sollten jedoch keines von beiden wirklich verwenden. Als Faustregel ist , dass mit sehr wenigen Ausnahmen abgesehen, sollten Sie immer verwenden "$foo"oder "${foo}"und nie $foooder ${foo}. Sie sollten Ihre Variablen immer in Anführungszeichen setzen, um den Aufruf des Operators split + glob zu vermeiden (dazu später mehr). Das willst du bestimmt nicht $foo$. Das Finale $ist irrelevant:

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

Während also nicht zitierte Variablen manchmal in Ordnung sind:

$ echo $foo
bar

Sie sind in der Regel nicht und sollten wirklich 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 nicht 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 $foooder verwenden ${foo}, teilt die Shell den in der Variablen im Leerzeichen gespeicherten Wert (dies kann geändert werden, indem die IFSVariable auf einen anderen Wert gesetzt wird ) in eine Liste auf. Anschließend wird jedes Element der Liste als Glob- Muster behandelt und erweitert alle passenden Dateien oder Verzeichnisse. Dies wird als Split + Glob- Operator bezeichnet. 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

Setzen wir nun eine Variable auf foo *:

$ foo="foo *"

Was passiert, wenn wir versuchen zu überprüfen, ob eine Datei mit diesem Namen vorhanden ist?

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

Die Variable wurde in aufgeteilt foound *da *es sich um einen Platzhalter handelt, der mit einer beliebigen Zeichenfolge übereinstimmt, teilt Ihnen die Shell mit, dass eine Datei mit dem Namen foo *exxists vorhanden ist. Wenn wir es jedoch richtig 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, um den Punkt zu veranschaulichen. Stellen Sie sich vor, ich hätte rmstattdessen verwendet echo.

Also, erste Regel: Zitieren Sie immer Ihre Variablen. Sie können entweder "$foo"oder "${foo}"aber so oder so zitieren. Weitere Informationen zur sicheren Verwendung von Variablen finden Sie in den folgenden Beiträgen:

Terdon
quelle
Ich wollte Ihre ansonsten ausgezeichnete Antwort nicht bearbeiten, sollte es aber nicht $ var="foo *"sein $ foo="foo *"? Sie verwenden varnirgendwo.
Joe
@ Joe oh, gute Trauer! Ja, natürlich sollte es, danke für den Hinweis. Fühlen Sie sich frei, solche Fehler zu beheben, indem Sie übrigens eine Bearbeitung vorschlagen. So etwas wird sehr empfohlen, gerade um dumme Fehler wie diesen zu vermeiden.
Terdon