@slm a déjà inclus les documents POSIX - qui sont très utiles - mais ils ne développent pas vraiment la manière dont ces paramètres peuvent être combinés pour s’affecter mutuellement. Il n'y a pas encore de mention ici de ce formulaire:
${var?if unset parent shell dies and this message is output to stderr}
Ceci est un extrait d’ 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
L'exemple ci - dessus profite de toutes les 4 formes de substitution de paramètres et de leurs différents POSIX :colon null
ou not null
tests. Il y a plus d'informations dans le lien ci-dessus, et le voici à nouveau .
Une autre chose à laquelle les gens ne pensent souvent pas, ${parameter:+expansion}
c'est à quel point cela peut être utile dans un document ici. Voici un autre extrait d'une réponse différente :
HAUT
Ici, vous définissez des valeurs par défaut et vous préparez à les imprimer lorsque vous êtes appelé ...
#!/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
MILIEU
C'est ici que vous définissez d'autres fonctions pour appeler votre fonction d'impression 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
}
BAS
Vous avez tout configuré maintenant, alors voici où vous allez exécuter et extraire vos résultats.
_less_important_function
: "${PLACE:="the cemetery"}"
_more_important_function
: "${RESULT:="regret it."}"
_less_important_function
RÉSULTATS
J'expliquerai pourquoi dans un instant, mais l'exécution de 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 j'ai vu Disney sur glace.
Si vous faites la calligraphie, vous réussirez.
ensuite _more_important_function():
Je suis allé au cimetière et j'ai vu Disney sur glace.
Si vous faites des mathématiques correctives, vous réussirez.
_less_important_function()
encore:
Je suis allé au cimetière et j'ai vu Disney sur glace.
Si vous faites des mathématiques correctives, vous le regretterez.
COMMENT ÇA FONCTIONNE:
La caractéristique clé ici est le concept de conditional ${parameter} expansion.
Vous pouvez définir une variable sur une valeur uniquement si elle est non définie ou nulle en utilisant le formulaire:
${var_name
: =desired_value}
Si, au lieu de cela, vous souhaitez définir uniquement une variable non définie, vous omettez les :colon
valeurs et null resteraient telles quelles.
SUR LA PORTÉE:
Vous remarquerez peut-être que, dans l'exemple ci-dessus $PLACE
, les $RESULT
modifications sont apportées lorsqu'elles sont définies via parameter expansion
même si elles _top_of_script_pr()
ont déjà été appelées, probablement en les configurant lors de leur exécution. La raison pour laquelle cela fonctionne est que _top_of_script_pr()
c'est une ( subshelled )
fonction - je l'ai incluse parens
plutôt que celle { curly braces }
utilisée pour les autres. Comme elle est appelée dans un sous-shell, toutes les variables qu'elle définit sont locally scoped
et, à mesure qu'elles retournent dans leur shell parent, ces valeurs disparaissent.
Mais lorsqu’il est _more_important_function()
défini, $ACTION
il en va de même globally scoped
pour la _less_important_function()'s
deuxième évaluation $ACTION
car _less_important_function()
, $ACTION
uniquement via${parameter:=expansion}.
man bash
; recherchez le bloc "Parameter Expansion" (environ 28%). Ces assignations sont par exemple des fonctions par défaut: "Utilisez la valeur par défaut uniquement si aucune n'a encore été définie."