Ich wollte oben in meinem Skript einige Zeichenfolgen mit Variablen initialisieren, die noch nicht festgelegt wurden, z.
str1='I went to ${PLACE} and saw ${EVENT}'
str2='If you do ${ACTION} you will ${RESULT}'
und dann später auf PLACE
, EVENT
, ACTION
und RESULT
wird eingestellt. Ich möchte dann in der Lage sein, meine Zeichenfolgen mit den erweiterten Variablen auszudrucken. Ist meine einzige Option eval
? Das scheint zu funktionieren:
eval "echo ${str1}"
ist das standard Gibt es einen besseren Weg, dies zu tun? Es wäre schön, nicht zu rennen, eval
wenn man bedenkt, dass die Variablen alles sein könnten.
Da ich Ihre Meinung verstehe, glaube ich nicht, dass eine dieser Antworten richtig ist.
eval
ist in keiner Weise notwendig, und Sie müssen Ihre Variablen auch nur zweimal auswerten.Es ist wahr, @Gilles kommt dem sehr nahe, aber er geht nicht auf das Problem möglicherweise überschreibender Werte ein und darauf, wie sie verwendet werden sollten, wenn Sie sie mehr als einmal benötigen. Eine Vorlage sollte doch mehrmals verwendet werden, oder?
Ich denke, es ist mehr die Reihenfolge, in der Sie sie bewerten, wichtig. Folgendes berücksichtigen:
OBEN
Hier legen Sie einige Standardeinstellungen fest und bereiten das Drucken vor, wenn Sie dazu aufgefordert werden ...
MITTE
Hier definieren Sie andere Funktionen, um Ihre Druckfunktion basierend auf deren Ergebnissen aufzurufen ...
UNTERSEITE
Sie haben jetzt alles eingerichtet. Hier können Sie Ihre Ergebnisse ausführen und abrufen.
ERGEBNISSE
Ich werde gleich auf das Warum eingehen, aber das Ausführen des obigen Befehls führt zu den folgenden Ergebnissen:
WIE ES FUNKTIONIERT:
Das Hauptmerkmal hierbei ist das Konzept von.
conditional ${parameter} expansion.
Sie können eine Variable nur dann auf einen Wert setzen, wenn sie in der folgenden Form nicht gesetzt oder null ist:Wenn Sie stattdessen nur eine nicht festgelegte Variable
:colon
festlegen möchten , lassen Sie die Werte weg, und Nullwerte bleiben unverändert .ON SCOPE:
Möglicherweise bemerken Sie dies im obigen Beispiel
$PLACE
und$RESULT
werden geändert, wenn die Einstellung über ausgeführt wirdparameter expansion
, obwohl_top_of_script_pr()
sie bereits aufgerufen wurde, und stellen sie vermutlich ein, wenn sie ausgeführt wird. Der Grund, warum dies funktioniert, ist, dass_top_of_script_pr()
es sich um eine( subshelled )
Funktion handelt - ich habe sie eingeschlossen,parens
anstatt{ curly braces }
sie für die anderen zu verwenden. Da es in einer Subshell aufgerufen wird, ist jede Variable, die es setzt,locally scoped
und wenn es zu seiner übergeordneten Shell zurückkehrt, verschwinden diese Werte.Aber wenn
_more_important_function()
setzt$ACTION
esglobally scoped
so wirkt es_less_important_function()'s
zweite Auswertung von$ACTION
da_less_important_function()
Sätze$ACTION
nur über${parameter:=expansion}.
:NULL
Und warum verwende ich das führende ?
:colon?
Nun, dieman
Seite sagt dir, dass: does nothing, gracefully.
du siehst,parameter expansion
genau wie es sich anhört - es hängtexpands
vom Wert des${parameter}.
Also, wenn wir eine Variable setzen,${parameter:=expansion}
bleiben wir beim Wert - was die Shell will Versuch, inline auszuführen. Wenn es versuchen würde zu laufenthe cemetery
, würde es nur einige Fehler auf Sie spucken.PLACE="${PLACE:="the cemetery"}"
würde die gleichen Ergebnisse liefern, aber es ist in diesem Fall auch überflüssig und ich bevorzuge die Shell: ${did:=nothing, gracefully}.
Dies können Sie tun:
HIER-DOKUMENTE
Übrigens: Die Inline-Definition einer Null- oder einer nicht gesetzten Variablen ist auch der Grund, warum Folgendes funktioniert:
Der beste Weg, sich
here-document
eine Datei vorzustellen, ist ein Streaming zu einem Eingabedateideskriptor. Mehr oder weniger sind sie das, aber verschiedene Schalen implementieren sie etwas anders.In jedem Fall, wenn Sie das nicht zitieren
<<LIMITER
, wird es gestreamt und ausgewertet.expansion.
Das Deklarieren einer Variablen in einemhere-document
kann funktionieren, aber nur überexpansion
welche Grenzen können Sie nur Variablen setzen, die noch nicht gesetzt sind. Dies entspricht jedoch genau Ihren Anforderungen, da Ihre Standardwerte immer festgelegt werden, wenn Sie die Funktion zum Drucken von Vorlagen aufrufen.WARUM NICHT
eval?
Nun, das Beispiel, das ich vorgestellt habe, bietet ein sicheres und effektives Mittel zum Akzeptieren.
parameters.
Da es den Gültigkeitsbereich behandelt, kann jede Variable innerhalb von set via${parameter:=expansion}
von außen definiert werden. Wenn Sie all dies in ein Skript namens template_pr.sh einfügen und ausführen:Sie würden bekommen:
Dies würde nicht für die Variablen funktionieren, die im Skript buchstäblich festgelegt wurden, wie
$EVENT, $ACTION,
und,$one,
aber ich habe diese nur so definiert, um den Unterschied zu demonstrieren.In jedem Fall ist die Annahme unbekannter Eingaben in eine
evaled
Anweisung inhärent unsicher, wohingegen sieparameter expansion
speziell dafür ausgelegt ist.quelle
Sie können Platzhalter für Zeichenfolgenvorlagen anstelle von nicht erweiterten Variablen verwenden. Dies wird ziemlich schnell chaotisch. Wenn das, was Sie tun, sehr vorlagenintensiv ist, sollten Sie eine Sprache mit einer echten Vorlagenbibliothek in Betracht ziehen.
Der Nachteil des oben Gesagten ist, dass die Template-Variable ein eigenes Wort sein muss (was Sie zB nicht können
"%prefix%foo"
). Dies könnte mit einigen Änderungen behoben werden, oder einfach durch festes Codieren der Vorlagenvariablen, anstatt dass sie dynamisch ist.quelle