Warum behält die Bash-Variablenerweiterung Anführungszeichen bei?

12
> echo "hi"
hi
> VAR='echo "hi"'
> $VAR
"hi"

Warum unterscheidet sich die Ausgabe der obigen Befehle?

Ähnliches gilt für einfache Anführungszeichen:

> VAR="echo 'hi'"
> $VAR
> 'hi'
Cory Klein
quelle
6
Gewöhnen Sie sich bitte nicht an, ausführbare Skript-Snippets in Variablen einzubetten. Dies ist im besten Fall schwierig und evalein Minenfeld von potenziellen Sicherheitslücken, die Sie sehr vorsichtig
betreten
@ jw013 Guter Punkt und tolle Artikel. Ich mag das Zitat "Variablen enthalten Daten, Funktionen enthalten Code." Vom ersten Link an, aber für meine Verwendung sind die Daten, die einer Funktion (in diesem Fall at) gegeben werden, Code. Gibt es Tipps, wie Sie Code sicherer organisieren / sammeln können at?
Cory Klein
atVerwendet die shSyntax als Eingabe. Das Erzeugen von Eingaben für atbedeutet, dass gültige, korrekt zitierte shSyntax aus beliebigen Eingaben generiert wird , was nicht trivial ist. Daher würde ich versuchen, dies zu vermeiden, wenn dies überhaupt möglich ist. Es wäre wirklich hilfreich, wenn Sie ein wenig detaillierter beschreiben könnten, was Sie erreichen möchten.
jw013
Entschuldigung, ich wollte nicht mit zu vielen Details ablenken, aber was ich tue, ist nicht wirklich kompliziert, IMO. Ich erstelle ein Skript, das eine "Zeit" und eine "Nachricht" benötigt. Es wird dann atfür die angegebene "Zeit" ausgeführt und weist atan, den Befehl auszuführen dzen2. dzen2Nimmt die "Nachricht" von stdin und verwendet auch einige andere statische Parameter. Die Schwierigkeit besteht darin , dass ich die „message“ Parameter vom Benutzer in dem zu Rohr benötigen dzen2Befehl, aber ich bin nicht wirklich laufe dzen2mich, ich sage ates zu tun.
Cory Klein

Antworten:

16

Das zusätzliche Paar von Anführungszeichen würde nur durch einen zusätzlichen Bewertungsschritt verbraucht. Zum Beispiel gezwungen durch eval:

bash-4.2$ VAR='echo "hi"'

bash-4.2$ $VAR
"hi"

bash-4.2$ eval $VAR
hi

Generell ist es jedoch eine schlechte Idee, Befehle mit Parametern in eine Zeichenfolge zu setzen. Verwenden Sie stattdessen ein Array:

bash-4.2$ VAR=(echo "hi")

bash-4.2$ "${VAR[@]}"
hi
Mann bei der Arbeit
quelle
1
Es ist auch wichtig zu beachten, dass Anführungszeichen unterschiedlich bewertet werden. doppelte Anführungszeichen ( ") erlauben Auswertung der eingeschlossenen Zeichenfolge, einfache Anführungszeichen ( ') die Zeichenfolge als eine wörtliche drucken . Beispiel: "$(ls)"und '$(ls)'Dies ist der Grund , warum Zitate in Originalfragen Beispiele erscheinen..
Joseph Kern
Ein Array ist auch eine Quelle von Problemen. Code gehört zu Funktionen, Daten zu Variablen. Das von Ihnen dargestellte Beispiel funktioniert nur, weil die Anführungszeichen in der Aufteilung des Arrays entfernt werden. A printf '<%s> ' "${VAR[@]}"zeigt an, dass Anführungszeichen bereits entfernt wurden. Wenn Sie VAR eingestellt , wie VAR=(echo \"hi\")tatsächlich Anführungszeichen haben, das gleiche Problem erneut angezeigt wird, $ ${VAR[@]}druckt"hi"
9

Das Entfernen von Anführungszeichen erfolgt nur für die ursprünglichen Eingabewörter, nicht für das Ergebnis von Erweiterungen. Anführungszeichen, die Teil erweiterter Variablen sind, bleiben unberührt.

jw013
quelle
2

Wenn Sie etwas zurücktreten, können Sie sehen, warum die Variablensubstitution Anführungszeichen unbedingt beibehalten sollte.

Der Sinn der Anführungszeichen in einer Unix / Linux / BSD-Shell besteht darin, Teile eines Strings zusammenzuhalten, die andernfalls als mehrere Strings analysiert würden. Da eine Shell standardmäßig Leerzeichen als Token-Trennzeichen verwendet, wird eine Zeichenfolge mit Leerzeichen (wie "eins zwei drei"), wenn sie nicht in Anführungszeichen gesetzt oder in irgendeiner Weise maskiert wird, als drei Zeichenfolgen analysiert: "eins", "zwei" und "drei".

Wenn ein Programmierer einen String mit dem Wert einer Variablen interpolieren möchte:

VAR=two
STRING="one $VAR three"

Die Shell sollte die Anführungszeichen auf keinen Fall entfernen: Die Zeichenfolge, die Leerzeichen enthält, wird als 3 kleinere Zeichenfolgen analysiert.

Bruce Ediger
quelle