Utilisation de “ $ {a: -b} ” pour laffectation de variables dans les scripts

Jai regardé quelques scripts que dautres personnes ont écrits (en particulier Red Hat), et beaucoup de leurs variables sont attribuées en utilisant la notation suivante VARIABLE1="${VARIABLE1:-some_val}" ou dautres développent dautres variables VARIABLE2="${VARIABLE2:-`echo $VARIABLE1`}"

Quel est lintérêt dutiliser cette notation au lieu de simplement déclarer les valeurs directement (par exemple, VARIABLE1=some_val )?

Y a-t-il des avantages à cette notation ou des erreurs possibles qui seraient évitées?

Le :- a-t-il une signification spécifique dans ce contexte ?

Commentaires

  • Jetez un œil à man bash; recherchez le bloc  » Expansion des paramètres  » (à environ 28%). Ces affectations sont par exemple fonctions par défaut:  » Utilisez la valeur par défaut uniquement si aucune na encore été définie.  »
  • Comme :- définit la valeur par défaut, le :+ est utilisé pour modifier la valeur si la variable est pas nul. Par exemple. v=option; cmd ${v:+ with $v} Exécutera  » cmd avec loption « . Mais si $ v est nul, il nexécuterait que  » cmd « .

Réponse

Cette technique permet dattribuer une valeur à une variable si une autre variable est vide ou non définie. REMARQUE: Cette « autre variable » peut être la même ou une autre variable.

extrait

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

REMARQUE: Ceci le formulaire fonctionne également, ${parameter-word}. Si vous « souhaitez voir une liste complète de toutes les formes dexpansion de paramètres disponibles dans Bash, je vous suggère fortement de jeter un œil à ce sujet dans le wiki de Bash Hacker intitulé: » Extension de paramètre « .

Exemples

la variable nexiste pas

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

variable existe

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

La même chose peut être faite en évaluant dautres variables ou en exécutant des commandes dans la partie valeur par défaut de la notation.

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

Autres exemples

Vous pouvez également utiliser une notation légèrement différente où il « est juste VARX=${VARX-<def. value>}.

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

Dans ce qui précède $VAR1 & $VAR2 étaient déjà définis avec la chaîne « a une autre valeur » mais $VAR3 nétait pas défini, la valeur par défaut a donc été utilisée à la place, 0.

Un autre exemple

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

Vérification et attribution en utilisant la notation :=

Enfin, je « mentionnerai lopérateur pratique, :=. Cela fera une vérification et attribuera une valeur si la variable sous test est vide ou non définie.

Exemple

Notez que $VAR1 est maintenant ensemble. Lopérateur := a fait le test et laffectation en une seule opération.

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

Cependant si la valeur est définie avant, alors il « est laissé seul.

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

Tableau de référence Handy Dandy

        ss du tableau

Références

Commentaires

  • Notez que toutes ces extensions ne sont pas documentées dans bash. Le ${var:-word} dans le Q est, mais pas le ${var-word} ci-dessus. Le POSIX la documentation a une belle table cependant, cela vaut peut-être la peine de la copier dans est la réponse – pubs.opengroup.org/onlinepubs/9699919799/utilities/…
  • @Graeme, cest documenté, il suffit de faire attention au Omettre les deux-points entraîne un test uniquement pour un paramètre non défini.
  • Utilisation de echo "${FOO:=default}" est parfait si vous voulez réellement le echo. Mais si vous ne ‘ t, essayez le : intégré … : ${FOO:=default} Votre $FOO est défini sur default comme ci-dessus (cest-à-dire sil nest pas déjà défini). Mais il ny a ‘ aucun écho de $FOO dans le processus.
  • Ok, jai trouvé une réponse: stackoverflow.com / q / 24405606/1172302 . Lutilisation de ${4:-$VAR} fonctionnera.
  • +1 juste pour la réponse détaillée. Mais aussi pour le fait que vous faites référence à lexcellent wiki bash. Et aussi pour le fait que vous donniez des exemples et un tableau. Enfer, juste + 1 tout en bas 🙂 Quant à moi, javais presque la syntaxe correcte mais pas tout à fait – je ne me suis ‘ pas assez soucieux de rechercher la page de manuel (pas difficile mais je ne pouvais pas ‘ me souvenir de quel titre il se trouvait et je ‘ suis réveillé depuis 4 ce matin :() ..

Réponse

@slm a déjà inclus les documents POSIX – qui sont très utiles – mais ils ne précisent pas vraiment comment ces paramètres peuvent être combinés pour sinfluencer les uns les autres. Il ny a pas encore de mention ici de cette forme:

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

Ceci est un extrait de une autre de mes réponses , et je pense que cela montre très bien comment cela fonctionne:

 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? 

Un autre exemple de même :

 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 

Lexemple ci-dessus tire parti des 4 formes de substitution de paramètres POSIX et leurs différents tests :colon null ou not null . Vous trouverez plus dinformations dans le lien ci-dessus et la voici à nouveau .

Une autre chose que les gens ne considèrent souvent pas à propos de ${parameter:+expansion} est à quel point cela peut être très utile dans un document ici. Voici un autre extrait dun réponse différente :

TOP

Ici, vous « allez définir quelques valeurs par défaut et vous préparer à les imprimer lors de lappel …

#!/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 

MIDDLE

Cest ici que vous définissez dautres fonctions à appeler sur votre fonction dimpression en fonction de leurs résultats …

 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 } 

BOTTOM

Vous avez tout configuré maintenant, alors voici « où vous » exécuterez et tirerez vos résultats.

 _less_important_function : "${PLACE:="the cemetery"}" _more_important_function : "${RESULT:="regret it."}" _less_important_function 

RÉSULTATS

Je vais expliquer pourquoi dans un instant, mais exécuter ce qui précède produit les résultats suivants:

_less_important_function()"s première exécution:

Je suis allé chez votre mère et jai vu Disney on Ice.

Si vous faites de la calligraphie , vous réussirez.

e fr _more_important_function():

Je suis allé au cimetière et jai vu Disney on Ice.

Si vous faites des mathématiques de rattrapage , vous réussirez.

_less_important_function() encore une fois:

Je suis allé au cimetière et jai vu Disney on Ice.

Si vous faites des mathématiques de rattrapage, vous le regretterez.

COMMENT ÇA MARCHE:

La caractéristique clé ici est le concept de conditional ${parameter} expansion. Vous pouvez définir une variable sur un valeur uniquement si elle nest pas définie ou nulle sous la forme:

${var_name : = desired_value}

Si à la place vous souhaitez définir uniquement une variable non définie, vous omettez le et les valeurs nulles resteraient telles quelles.

SUR LE CHAMP DAPPLICATION:

Vous remarquerez peut-être que dans lexemple ci-dessus $PLACE et $RESULT sont modifiés lorsquils sont définis via parameter expansion même si _top_of_script_pr() a déjà été appelé, sans doute en les définissant lors de son exécution. La raison pour laquelle cela fonctionne est que _top_of_script_pr() est une fonction ( subshelled ) – jai inclus dans parens plutôt que dans le { curly braces } utilisé pour les autres. Puisquelle est appelée dans un sous-shell, chaque variable quelle définit est locally scoped et lorsquelle retourne à son shell parent, ces valeurs disparaissent.

Mais lorsque _more_important_function() définit $ACTION cest globally scoped donc cela affecte _less_important_function()"s deuxième évaluation de $ACTION car _less_important_function() définit $ACTION uniquement via ${parameter:=expansion}.

Commentaires

  • Cest bien de voir que la valeur par défaut du raccourci fonctionne dans Bourne Shell

Réponse

Expérience personnelle.

Jutilise parfois ce format dans mes scripts pour remplacer des valeurs ad hoc, par exemplesi jai:

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

je peux exécuter:

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

sans avoir à changer la valeur par défaut dorigine de SOMETHING.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *