Si je comprends bien votre sens, je ne crois pas que ces réponses soient correctes. eval
n'est en aucun cas nécessaire, et vous n'avez même pas besoin d'évaluer deux fois vos variables.
C'est vrai, @Gilles s'en approche de très près, mais il ne résout pas le problème de la substitution éventuelle des valeurs et comment elles devraient être utilisées si vous en avez besoin plusieurs fois. Après tout, un modèle doit être utilisé plusieurs fois, non?
Je pense que c'est plus l'ordre dans lequel vous les évaluez qui est important. Considérer ce qui suit:
HAUT
Ici, vous allez définir des valeurs par défaut et vous préparer à les imprimer lors de l'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 faire appel à 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 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 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 ta mère et j'ai vu Disney sur glace.
Si vous faites de 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 de rattrapage, 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, à la place, vous souhaitez définir uniquement une variable non définie, vous omettriez les :colon
valeurs nulles et resteraient telles quelles.
SUR LA PORTÉE:
Vous remarquerez peut-être que dans l'exemple ci-dessus $PLACE
et que $RESULT
vous vous changez lorsqu'il est défini via, parameter expansion
même s'il _top_of_script_pr()
a déjà été appelé, il est probable qu'il soit défini lors de son 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. Parce qu'elle est appelée dans un sous-shell, chaque variable qu'elle définit estlocally scoped
et lorsqu'elle retourne à son shell parent, ces valeurs disparaissent.
Mais quand des _more_important_function()
jeux , $ACTION
il est globally scoped
donc elle affecte _less_important_function()'s
deuxième évaluation de $ACTION
car _less_important_function()
ensembles $ACTION
uniquement par${parameter:=expansion}.
:NUL
Et pourquoi dois-je utiliser le premier :colon?
Eh bien, la man
page vous dira que : does nothing, gracefully.
vous voyez, parameter expansion
c'est exactement ce que cela ressemble - expands
à la valeur de ${parameter}.
Donc, lorsque nous définissons une variable avec ${parameter:=expansion}
nous nous retrouvons avec sa valeur - que le shell tenter d'exécuter en ligne. S'il essayait de s'exécuter, the cemetery
il vous cracherait juste quelques erreurs. PLACE="${PLACE:="the cemetery"}"
produirait les mêmes résultats, mais c'est aussi redondant dans ce cas et j'ai préféré que la coque: ${did:=nothing, gracefully}.
Cela vous permet de faire ceci:
echo ${var:=something or other}
echo $var
something or other
something or other
ICI-DOCUMENTS
Et en passant - la définition en ligne d'une variable nulle ou non définie est également la raison pour laquelle les éléments suivants fonctionnent:
<<HEREDOC echo $yo
${yo=yoyo}
HEREDOC
yoyo
La meilleure façon de penser à un here-document
est comme un fichier réel diffusé vers un descripteur de fichier d'entrée. C'est plus ou moins ce qu'ils sont, mais différents shells les implémentent légèrement différemment.
Dans tous les cas, si vous ne citez pas le, <<LIMITER
vous l'obtenez en flux continu et évalué pour expansion.
Ainsi, déclarer une variable dans un here-document
peut fonctionner, mais uniquement via expansion
ce qui vous limite à définir uniquement des variables qui ne sont pas déjà définies. Pourtant, cela correspond parfaitement à vos besoins tels que vous les avez décrits, car vos valeurs par défaut seront toujours définies lorsque vous appelez la fonction d'impression de votre modèle.
POURQUOI PAS eval?
Eh bien, l'exemple que j'ai présenté fournit un moyen sûr et efficace d'accepter parameters.
Parce qu'il gère la portée, chaque variable dans set via ${parameter:=expansion}
est définissable de l'extérieur. Donc, si vous mettez tout cela dans un script appelé template_pr.sh et que vous exécutez:
% RESULT=something_else template_pr.sh
Vous obtiendriez:
Je suis allé chez ta mère et j'ai vu Disney sur glace
Si vous faites de la calligraphie, vous aurez quelque chose_else
Je suis allé au cimetière et j'ai vu Disney sur glace
Si vous faites des mathématiques de rattrapage, vous aurez quelque chose d'autre
Je suis allé au cimetière et j'ai vu Disney sur glace
Si vous faites des mathématiques de rattrapage, vous aurez quelque chose d'autre
Cela ne fonctionnerait pas pour les variables qui ont été définies littéralement dans le script, comme $EVENT, $ACTION,
et $one,
mais je les ai définies de cette manière uniquement pour démontrer la différence.
Dans tous les cas, l'acceptation d'une entrée inconnue dans une evaled
instruction est intrinsèquement dangereuse, alors qu'elle parameter expansion
est spécifiquement conçue pour le faire.