Verwenden von “ $ {a: -b} ” für die Variablenzuweisung in Skripten

Ich habe mir einige Skripte angesehen, die andere geschrieben haben (insbesondere Red Hat), und viele ihrer Variablen werden mit der folgenden Notation VARIABLE1="${VARIABLE1:-some_val}" zugewiesen oder einige erweitern andere Variablen VARIABLE2="${VARIABLE2:-`echo $VARIABLE1`}"

Wozu dient diese Notation, anstatt nur die Werte direkt zu deklarieren (z. B. VARIABLE1=some_val? )?

Gibt es Vorteile für diese Notation oder mögliche Fehler, die verhindert werden könnten?

Hat die :- in diesem Zusammenhang eine spezifische Bedeutung ?

Kommentare

  • Schauen Sie sich man bash an. Suche nach dem Block “ Parametererweiterung “ (bei ca. 28%). Diese Zuordnungen sind z.B. Standardfunktionen: “ Verwenden Sie den Standardwert nur, wenn noch keiner festgelegt wurde. “
  • Als :- legt den Standardwert fest. Die :+ wird verwendet, um den Wert zu ändern, wenn die Variable dies ist nicht null. Z.B. v=option; cmd ${v:+ with $v} Führt “ cmd mit der Option “ aus. Wenn $ v jedoch null ist, wird nur “ cmd “ ausgeführt.

Antwort

Mit dieser Technik kann einer Variablen ein Wert zugewiesen werden, wenn eine andere Variable entweder leer oder undefiniert ist. HINWEIS: Diese „andere Variable“ kann dieselbe oder eine andere Variable sein.

Auszug

${parameter:-word} If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted. 

HINWEIS: Dies Form funktioniert auch, ${parameter-word}. Wenn Sie eine vollständige Liste aller in Bash verfügbaren Formen der Parametererweiterung sehen möchten, empfehle ich Ihnen dringend, sich dieses Thema im Wiki des Bash Hacker mit dem Titel „ Parametererweiterung „.

Beispiele

Variable existiert nicht

$ echo "$VAR1" $ VAR1="${VAR1:-default value}" $ echo "$VAR1" default value 

Variable existiert

$ VAR1="has value" $ echo "$VAR1" has value $ VAR1="${VAR1:-default value}" $ echo "$VAR1" has value 

Dasselbe kann durch Auswerten anderer Variablen oder Ausführen von Befehlen innerhalb des Standardwertteils der Notation erfolgen.

$ VAR2="has another value" $ echo "$VAR2" has another value $ echo "$VAR1" $ $ VAR1="${VAR1:-$VAR2}" $ echo "$VAR1" has another value 

Weitere Beispiele

Sie können auch eine etwas andere Notation verwenden, wenn es sich nur um VARX=${VARX-<def. value>} handelt. P. >

$ echo "${VAR1-0}" has another value $ echo "${VAR2-0}" has another value $ echo "${VAR3-0}" 0 

Im obigen $VAR1 & $VAR2 wurden bereits mit der Zeichenfolge „hat einen anderen Wert“ definiert, aber $VAR3 war undefiniert, sodass stattdessen der Standardwert 0.

Ein weiteres Beispiel

$ VARX="${VAR3-0}" $ echo "$VARX" 0 

Überprüfen und Zuweisen mit der := -Notation

Zuletzt werde ich den praktischen Operator :=. Dies führt eine Überprüfung durch und weist einen Wert zu, wenn die zu testende Variable leer oder undefiniert ist.

Beispiel

Beachten Sie, dass $VAR1 jetzt ist einstellen. Der Operator := hat den Test und die Zuweisung in einer einzigen Operation durchgeführt.

$ unset VAR1 $ echo "$VAR1" $ echo "${VAR1:=default}" default $ echo "$VAR1" default 

Wenn jedoch der Wert festgelegt ist vorher, dann wird es alleine gelassen.

$ VAR1="some value" $ echo "${VAR1:=default}" some value $ echo "$VAR1" some value 

Handy Dandy Referenztabelle

        ss der Tabelle

Referenzen

Kommentare

  • Beachten Sie, dass nicht alle dieser Erweiterungen in bash. Die ${var:-word} im Q ist, aber nicht die ${var-word} oben. Die POSIX Dokumentation hat eine schöne Tabelle, könnte es wert sein, sie in th zu kopieren ist die Antwort – pubs.opengroup.org/onlinepubs/9699919799/utilities/…
  • @Graeme, es ist dokumentiert, Sie müssen nur auf das Auslassen des Doppelpunkts achten, was zu einem Test nur für einen Parameter führt, der nicht gesetzt ist.
  • Verwenden von echo "${FOO:=default}" ist großartig, wenn Sie tatsächlich die echo möchten. Wenn Sie jedoch nicht ‚ t verwenden, versuchen Sie es mit dem integrierten :: ${FOO:=default} Ihre $FOO ist wie oben beschrieben auf default gesetzt (dh falls nicht bereits festgelegt). Aber ‚ gibt kein Echo von $FOO in diesem Prozess.
  • Ok, habe eine Antwort gefunden: Stapelüberlauf.com / q / 24405606/1172302 . Die Verwendung von ${4:-$VAR} funktioniert.
  • +1 nur für die detaillierte Antwort. Aber auch dafür, dass Sie auf das exzellente Bash-Wiki verweisen. Und auch dafür, dass Sie Beispiele und eine Tabelle geben. Zur Hölle, nur +1s ganz unten 🙂 Was mich betrifft, hatte ich fast die richtige Syntax, aber nicht ganz – ich habe mich nur nicht darum gekümmert, die Manpage zu durchsuchen (nicht schwer). ‚ aber ich konnte mich ‚ nicht erinnern, unter welcher Überschrift es sich befand, und ‚ war heute Morgen seit 4 Uhr wach :() ..

Antwort

@slm enthält bereits die POSIX-Dokumente – die sehr hilfreich sind – aber sie erweitern nicht wirklich, wie diese Parameter kombiniert werden können, um sich gegenseitig zu beeinflussen. Diese Form wird hier noch nicht erwähnt:

${var?if unset parent shell dies and this message is output to stderr} 

Dies ist ein Auszug aus einer anderen Antwort von mir, und ich denke, sie zeigt sehr gut, wie diese funktionieren:

 sh <<-\CMD _input_fn() { set -- "$@" #redundant echo ${*?WHERES MY DATA?} #echo is not necessary though shift #sure hope we have more than $1 parameter : ${*?WHERES MY DATA?} #: do nothing, gracefully } _input_fn heres some stuff _input_fn one #here # shell dies - third try doesnt run _input_fn you there? # END CMD heres some stuff one sh: line :5 *: WHERES MY DATA? 

Ein weiteres Beispiel aus same :

 sh <<-\CMD N= #N is NULL _test=$N #_test is also NULL and v="something you would rather do without" ( #this subshell dies echo "v is ${v+set}: and its value is ${v:+not NULL}" echo "So this ${_test:-"\$_test:="} will equal ${_test:="$v"}" ${_test:+${N:?so you test for it with a little nesting}} echo "sure wish we could do some other things" ) ( #this subshell does some other things unset v #to ensure it is definitely unset echo "But here v is ${v-unset}: ${v:+you certainly wont see this}" echo "So this ${_test:-"\$_test:="} will equal NULL ${_test:="$v"}" ${_test:+${N:?is never substituted}} echo "so now we can do some other things" ) #and even though we set _test and unset v in the subshell echo "_test is still ${_test:-"NULL"} and ${v:+"v is still $v"}" # END CMD v is set: and its value is not NULL So this $_test:= will equal something you would rather do without sh: line 7: N: so you test for it with a little nesting But here v is unset: So this $_test:= will equal NULL so now we can do some other things _test is still NULL and v is still something you would rather do without 

Das obige Beispiel nutzt alle 4 Formen der POSIX-Parametersubstitution und ihre verschiedenen :colon null oder not null -Tests. Weitere Informationen finden Sie im obigen Link, und hier ist es wieder .

Eine andere Sache, die die Leute bei ${parameter:+expansion} oft nicht berücksichtigen, ist, wie sehr nützlich es in einem Here-Dokument sein kann. Hier ist ein weiterer Auszug aus einem andere Antwort :

TOP

Hier legen Sie einige Standardeinstellungen fest und bereiten den Druck vor, wenn Sie aufgerufen 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 

MITTEL

Hier definieren Sie andere Funktionen, die Ihre Druckfunktion basierend auf ihren Ergebnissen aufrufen sollen …

 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 } 

UNTEN

Sie haben jetzt alles eingerichtet, also werden Sie hier 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 der obigen Schritte führt zu den folgenden Ergebnissen:

_less_important_function()"s erster Lauf:

Ich ging zum Haus Ihrer Mutter und sah Disney on Ice.

Wenn Sie Kalligraphie machen, werden Sie Erfolg haben.

th de _more_important_function():

Ich ging zum Friedhof und habe Disney on Ice gesehen.

Wenn Sie Abhilfemathematik durchführen, werden Sie Erfolg haben.

_less_important_function() noch einmal:

Ich ging zum Friedhof und sah Disney on Ice.

Wenn Sie Abhilfemathematik betreiben, werden Sie es bereuen.

WIE ES FUNKTIONIERT:

Das Hauptmerkmal hier ist das Konzept von conditional ${parameter} expansion. Sie können eine Variable auf a setzen Wert nur, wenn er in der folgenden Form nicht gesetzt oder null ist:

${var_name : = desired_value}

Wenn Sie stattdessen nur eine nicht gesetzte Variable festlegen möchten, würden Sie das und Nullwerte bleiben unverändert.

IM GELTUNGSBEREICH:

Möglicherweise stellen Sie fest, dass im obigen Beispiel $PLACE und $RESULT werden geändert, wenn sie über parameter expansion , obwohl _top_of_script_pr() bereits aufgerufen wurde, und setzt sie vermutlich, wenn es ausgeführt wird. Der Grund dafür ist, dass _top_of_script_pr() eine ( subshelled ) -Funktion ist – ich habe beigefügt es in parens anstelle der { curly braces } , die für die anderen verwendet wird. 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() $ACTION setzt, ist es globally scoped wirkt sich also auf _less_important_function()"s zweite Auswertung von $ACTION , weil _less_important_function() $ACTION nur über ${parameter:=expansion}.

Kommentare

  • Gut zu sehen, dass der Standardwert für Kurzschrift funktioniert in Bourne Shell

Antwort

Persönliche Erfahrung.

Ich verwende dieses Format manchmal in meinen Skripten, um Ad-hoc-Überschreibungen von Werten durchzuführen, z.Wenn ich Folgendes habe:

$ cat script.sh SOMETHING="${SOMETHING:-something}"; echo "$SOMETHING"; 

Ich kann Folgendes ausführen:

$ env SOMETHING="something other than the default value" ./script.sh` 

ohne Änderungen vornehmen zu müssen Der ursprüngliche Standardwert von SOMETHING.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.