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.