
Ich neige dazu, Befehlsersetzungen wie unten gezeigt in Anführungszeichen zu setzen, selbst wenn ich ihre Ausgabe einer Variablen zuweise:
var="$(command)"
Ist das wirklich nötig? Wann geht es kaputt? Die akzeptierte AntwortHierAnsprüche:
DIRNAME="$(Verzeichnisname $FILE)"wird nicht tun, was Sie wollenwenn $FILE Leerzeichen oder Globbing-Zeichen enthält [?*.
Der Link verweist auf die großartige Seite von Grey Cat Wiki über das Zitieren, aber diese Seite erwähnt das Zitieren von Befehlssubstitutionen nicht ausdrücklich. Und während des Zitierens derVariableist eindeutig erforderlich, das Zitieren der Befehlsersetzung selbst scheint jedoch nicht erforderlich zu sein.
Derselbe Beitrag endet jedoch mit:
DIRNAME="$(dirname "$FILE")" ist die empfohlene Vorgehensweise. Sie können DIRNAME= durch einen Befehl und ein Leerzeichen ersetzen, ohne sonst etwas zu ändern, und dirname erhält die richtige Zeichenfolge.
Das habe ich auch immer gedacht und habe hier oft Beiträge korrigiert, die es nicht zitierten. Auf der oben verlinkten Wiki-Seite wird jedoch auch Folgendes behauptet:
In einigen Fällen können doppelte Anführungszeichen problemlos weggelassen werden:
Auf der rechten Seite einer einfachen Zuweisung. Sie können foo=$bar ohne Anführungszeichen schreiben. Dies ist POSIX-kompatibel.
[. . . ]
Obwohl var=$(command)
es sich nicht wirklich um eine „einfache“ Aufgabe handelt, konnte ich dennoch keinen Fall finden, in dem die Anführungszeichen tatsächlich notwendig waren:
$ var=$(echo "foo bar baz") ## whitespace works
$ echo "$var"
foo bar baz
$ var=$(printf "foo\nbar * baz") ## so do globbing characters
$ echo "$var"
foo
bar * baz
$ var1="foo\nbar * baz"
$ var=$(printf "$var1") ## printing a variable doesn't make any difference
$ echo "$var"
foo
bar * baz
$ var=$(printf '%s\n' "$var1")
$ echo "$var"
foo\nbar * baz
$ var=$(printf -- '-e %s\n' "$var1") ## strings starting with - also work
$ echo "$var"
-e foo\nbar * baz
Natürlich sind die Anführungszeichen unbedingt erforderlich, wenn die Befehlsersetzung direkt für Dinge wie verwendet wird command1 "$(command2)"
, aber das scheint bei der Zuweisung an eine Variable nicht der Fall zu sein.
Also, was übersehe ich? Werden die Anführungszeichen jemals benötigt? In welchem Sonderfall wird das Zitieren einer Befehlsersetzungbei der Zuweisung des Rückgabewertes an eine Variableschützen? Oder ist es immer in Ordnung, eine Befehlsersetzung nicht zu zitieren, wenn es sich um die rechte Seite einer Variablenzuweisungsoperation handelt?
Antwort1
Du tustnicht brauchenum den Ausdruck auf der rechten Seite einer Zuweisung zu zitieren.
Was Sie irritiert, ist, dass die andere Antwortempfiehlttrotzdem zu zitieren. Aber hier geht es nur um Codepflege.
Folgendes berücksichtigenrichtigBeispiel:
DIRNAME=$(dirname "$FILE")
echo "debug: dirname is $DIRNAME"
ls "$DIRNAME"
Nach einer Weile mit diesem Skript denken Sie vielleicht, dass die Debug-Meldung entfernt werden könnte. Entfernen Sie also mit einem Editor die Echo-Zeile. Dann werden Sie feststellen, dass Sie die Variable DIRNAME nicht einmal mehr benötigen und verschieben den ls
Befehl einfach, um die linke Seite der Zuweisung zu ersetzen. Jetzt können Sievergessen Sie, die erforderlichen Anführungszeichen hinzuzufügenund am Ende hast du das hierdefektes Skript:
ls $(dirname "$FILE")
Die Wahrscheinlichkeit für einen solchen Fehler ist sogar noch höher, wenn der erste Autor ein Shell-Experte ist, der zweite Editor jedoch ein Neuling.
Es ist natürlich fraglich, ob diesEmpfehlung, eine portable Shell-Funktion zu vermeidenist wirklich nützlich. Persönlich mache ich es meistens so, wie er es empfiehlt. Ich mache das auch für die „einfacheren“ Aufgaben wie: var="${foo}"
(auch mit überflüssigen geschweiften Klammern).
Antwort2
Als eine Referenz:Das Handbuch von Bash ist diesbezüglich eindeutig:
Einer Variablen kann eine Anweisung der Form
name=[value]
Wenn kein Wert angegeben ist, wird der Variablen die Nullzeichenfolge zugewiesen. Alle Werte werden einer Tilde-Erweiterung, einer Parameter- und Variablenerweiterung, einer Befehlsersetzung, einer arithmetischen Erweiterung und einer Anführungszeichenentfernung unterzogen (siehe unten). [...]Es wird keine Worttrennung durchgeführt, mit Ausnahme von „$@“, wie unten erläutert.Eine Dateinamenerweiterung wird nicht durchgeführt.
Keine Worttrennung, keine Dateinamenerweiterung, daher keine Anführungszeichen erforderlich.
Wie bei POSIX, Abschnitt2.9.1 Einfache Befehle:
2. Die Wörter, die keine Variablenzuweisungen oder -umleitungen sind, müssen erweitert werden. Wenn nach ihrer Erweiterung noch Felder übrig bleiben, gilt das erste Feld als Befehlsname und die übrigen Felder als Argumente für den Befehl.
[...]
4. Jede Variablenzuweisung muss vor der Zuweisung des Werts für Tilde-Erweiterung, Parametererweiterung, Befehlsersetzung, arithmetische Erweiterung und Anführungszeichenentfernung erweitert werden.
Ich bin mir nicht sicher, ob das so zu verstehen ist, dass die Feldaufteilung nur für Erweiterungen erfolgt, die in Schritt 2 durchgeführt werden? Schritt 4 tutnichterwähnen Feldaufteilung, obwohl der Abschnitt überFeldaufteilungerwähnt auch nicht die Variablenzuweisung als Ausnahme zur Erstellung mehrerer Felder.