Como eu entendo o seu significado, não acredito que nenhuma dessas respostas esteja correta. eval não é necessário de forma alguma, nem você precisa sequer avaliar duas vezes suas variáveis.
É verdade que @Gilles chega muito perto, mas ele não resolve o problema de possivelmente sobrepor valores e como eles devem ser usados se você precisar deles mais de uma vez. Afinal, um modelo deve ser usado mais de uma vez, certo?
Eu acho que é mais a ordem em que você os avalia que é importante. Considere o seguinte:
TOP
Aqui você pode definir alguns padrões e se preparar para imprimi-los quando chamado ...
#!/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
MÉDIO
Aqui é onde você define outras funções para chamar sua função de impressão com base em seus resultados ...
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
}
FUNDO
Você tem tudo configurado agora, então é aqui que você executará e extrairá seus resultados.
_less_important_function
: "${PLACE:="the cemetery"}"
_more_important_function
: "${RESULT:="regret it."}"
_less_important_function
RESULTADOS
Vou falar sobre o porquê daqui a pouco, mas a execução acima produz os seguintes resultados:
_less_important_function()'s first run:
I went to your mother's house and saw Disney on Ice.
If you do calligraphy you will succeed.
então _more_important_function():
I went to the cemetery and saw Disney on Ice.
If you do remedial mathematics you will succeed.
_less_important_function() novamente:
I went to the cemetery and saw Disney on Ice.
If you do remedial mathematics you will regret it.
COMO FUNCIONA:
A principal característica aqui é o conceito de conditional ${parameter} expansion. Você pode definir uma variável para um valor somente se ela não estiver definida ou nula usando o formulário:
${var_name:=desired_value}
Se, em vez disso, você quiser definir apenas uma variável não definida, omita o :colon e os valores nulos permanecerão como estão.
ON SCOPE:
Você pode notar que no exemplo acima $PLACE e $RESULT são alterados quando definidos via parameter expansion embora < em> _top_of_script_pr() já foi chamado, presumivelmente definindo-os quando é executado. A razão pela qual isso funciona é que _top_of_script_pr() é uma função ( subshelled ) - coloquei em parens em vez de { curly braces } usado para os outros. Como ele é chamado em um subshell, cada variável que ele configura é locally scoped e, quando retorna ao shell pai, esses valores desaparecem.
Mas quando _more_important_function() define $ACTION , é globally scoped , portanto, afeta _less_important_function()'s segunda avaliação de $ACTION porque _less_important_function() define $ACTION somente por ${parameter:=expansion}.
: NULL
E por que eu uso o :colon? ? Bem, a página man diz que : does nothing, gracefully. , parameter expansion é exatamente o que parece - é expands com o valor ${parameter}. Então quando definimos uma variável com ${parameter:=expansion} ficamos com seu valor - que o shell tentará executar em linha. Se ele tentou rodar the cemetery , ele iria cuspir alguns erros em você. PLACE="${PLACE:="the cemetery"}" produziria os mesmos resultados, mas também é redundante neste caso e eu preferi que o shell : ${did:=nothing, gracefully}.
Ele permite que você faça isso:
echo ${var:=something or other}
echo $var
something or other
something or other
AQUI DOCUMENTOS
E a propósito - a definição em linha de uma variável nula ou não definida é também a razão pela qual os seguintes trabalhos:
<<HEREDOC echo $yo
${yo=yoyo}
HEREDOC
yoyo
A melhor maneira de pensar em um here-document é como um arquivo real transmitido para um descritor de arquivo de entrada. Mais ou menos isso é o que eles são, mas diferentes shells os implementam de maneira um pouco diferente.
Em qualquer caso, se você não citar o <<LIMITER , ele será transmitido em e avaliado em expansion. Portanto, declarar uma variável em um here-document pode funcionar, mas somente via expansion , o que limita a configuração apenas de variáveis que ainda não estão definidas . Ainda assim, isso se ajusta perfeitamente às suas necessidades como você as descreveu, já que os valores padrão sempre serão definidos quando você chamar a função de impressão do modelo.
POR QUE NÃO eval?
Bem, o exemplo que apresentei fornece um meio seguro e eficaz de aceitar parameters. Como ele trata o escopo, todas as variáveis dentro do conjunto são ${parameter:=expansion} definível a partir do exterior. Então, se você colocar tudo isso em um script chamado template_pr.sh e executar:
% RESULT=something_else template_pr.sh
Você teria:
I went to your mother's house and saw Disney on Ice
If you do calligraphy you will something_else
I went to the cemetery and saw Disney on Ice
If you do remedial mathematics you will something_else
I went to the cemetery and saw Disney on Ice
If you do remedial mathematics you will something_else
Isso não funcionaria para as variáveis que foram definidas literalmente no script, como $EVENT, $ACTION, e $one, , mas eu defini apenas as desse modo para demonstrar a diferença.
Em qualquer caso, a aceitação de entrada desconhecida em uma instrução evaled é inerentemente insegura, enquanto parameter expansion é especificamente projetada para fazê-lo.