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 ...
#!/bin/sh
_top_of_script_pr() (
IFS="$nl" ; set -f #only split at newlines and don't expand paths
printf %s\\n ${strings}
) 3<<-TEMPLATES
${nl=
}
${PLACE:="your mother's house"}
${EVENT:="the unspeakable."}
${ACTION:="heroin"}
${RESULT:="succeed."}
${strings:="
I went to ${PLACE} and saw ${EVENT}
If you do ${ACTION} you will ${RESULT}
"}
#END
TEMPLATES
MITTE
Hier definieren Sie andere Funktionen, um Ihre Druckfunktion basierend auf deren Ergebnissen aufzurufen ...
EVENT="Disney on Ice."
_more_important_function() { #...some logic...
[ $((1+one)) -ne 2 ] && ACTION="remedial mathematics"
_top_of_script_pr
}
_less_important_function() { #...more logic...
one=2
: "${ACTION:="calligraphy"}"
_top_of_script_pr
}
UNTERSEITE
Sie haben jetzt alles eingerichtet. Hier können Sie Ihre Ergebnisse ausführen und abrufen.
_less_important_function
: "${PLACE:="the cemetery"}"
_more_important_function
: "${RESULT:="regret it."}"
_less_important_function
ERGEBNISSE
Ich werde gleich auf das Warum eingehen, aber das Ausführen des obigen Befehls führt zu den folgenden Ergebnissen:
_less_important_function()'s
erster Lauf:
Ich bin zum Haus deiner Mutter gegangen und habe Disney on Ice gesehen.
Wenn Sie Kalligraphie machen, werden Sie Erfolg haben.
dann _more_important_function():
Ich ging zum Friedhof und sah Disney on Ice.
Wenn Sie Heilmathematik machen, werden Sie Erfolg haben.
_less_important_function()
nochmal:
Ich ging zum Friedhof und sah Disney on Ice.
Wenn Sie Heilmathematik machen, werden Sie es bereuen.
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:
${var_name
: =desired_value}
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 wird parameter 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
es globally 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, die man
Seite sagt dir, dass : does nothing, gracefully.
du siehst, parameter expansion
genau wie es sich anhört - es hängt expands
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 laufen the 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:
echo ${var:=something or other}
echo $var
something or other
something or other
HIER-DOKUMENTE
Übrigens: Die Inline-Definition einer Null- oder einer nicht gesetzten Variablen ist auch der Grund, warum Folgendes funktioniert:
<<HEREDOC echo $yo
${yo=yoyo}
HEREDOC
yoyo
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 einem here-document
kann funktionieren, aber nur über expansion
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:
% RESULT=something_else template_pr.sh
Sie würden bekommen:
Ich bin zum Haus deiner Mutter gegangen und habe Disney on Ice gesehen
Wenn Sie Kalligraphie tun, werden Sie etwas_else
Ich ging zum Friedhof und sah Disney on Ice
Wenn Sie Heilmathematik machen, werden Sie etwas_else
Ich ging zum Friedhof und sah Disney on Ice
Wenn Sie Heilmathematik machen, werden Sie etwas_else
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 sie parameter expansion
speziell dafür ausgelegt ist.