A medida que entiendo su significado, no creo que ninguna de estas respuestas sea correcta. eval
no es necesario de ninguna manera, ni tiene ninguna necesidad incluso de evaluar dos veces sus variables.
Es cierto, @Gilles se acerca mucho, pero no aborda el problema de posiblemente anular los valores y cómo deberían usarse si los necesita más de una vez. Después de todo, una plantilla debe usarse más de una vez, ¿verdad?
Creo que es más importante el orden en el que los evalúas. Considera lo siguiente:
PARTE SUPERIOR
Aquí establecerá algunos valores predeterminados y se preparará para imprimirlos cuando se llame ...
#!/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
MEDIO
Aquí es donde define otras funciones para llamar a su función de impresión en función de sus 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
}
FONDO
Ya lo tiene todo configurado, así que aquí es donde ejecutará y extraerá sus resultados.
_less_important_function
: "${PLACE:="the cemetery"}"
_more_important_function
: "${RESULT:="regret it."}"
_less_important_function
RESULTADOS
Analizaré por qué en un momento, pero ejecutar lo anterior produce los siguientes resultados:
_less_important_function()'s
primer intento:
Fui a la casa de tu madre y vi Disney on Ice.
Si haces caligrafía tendrás éxito.
luego _more_important_function():
Fui al cementerio y vi Disney on Ice.
Si haces matemáticas correctivas tendrás éxito.
_less_important_function()
de nuevo:
Fui al cementerio y vi Disney on Ice.
Si haces matemáticas correctivas te arrepentirás.
CÓMO FUNCIONA:
La característica clave aquí es el concepto de conditional ${parameter} expansion.
Puede establecer una variable en un valor solo si no está establecida o es nula utilizando el formulario:
${var_name
: =desired_value}
Si, en cambio, desea establecer solo una variable no establecida, omitirá los :colon
valores nulos y permanecerá como está.
EN ALCANCE:
Puede notar eso en el ejemplo anterior $PLACE
y $RESULT
cambiarlo cuando se configura a través de parameter expansion
aunque _top_of_script_pr()
ya se haya llamado, presumiblemente configurándolos cuando se ejecuta. La razón por la que esto funciona es que _top_of_script_pr()
es una ( subshelled )
función: la incluí en parens
lugar de la { curly braces }
utilizada para los demás. Debido a que se llama en una subshell, cada variable que establece es locally scoped
y cuando regresa a su shell principal esos valores desaparecen.
Pero cuando se _more_important_function()
establece $ACTION
es globally scoped
así, afecta a la _less_important_function()'s
segunda evaluación de $ACTION
porque _less_important_function()
establece $ACTION
solo a través de${parameter:=expansion}.
:NULO
¿Y por qué utilizo el :colon?
Pozo principal? La man
página te dirá que : does nothing, gracefully.
, como ves, parameter expansion
es exactamente lo que suena, expands
al valor de ${parameter}.
So, cuando establecemos una variable con, ${parameter:=expansion}
nos queda su valor, que el shell Intente ejecutar en línea. Si intentara ejecutarse the cemetery
, solo te escupiría algunos errores. PLACE="${PLACE:="the cemetery"}"
produciría los mismos resultados, pero también es redundante en este caso y preferí que el shell: ${did:=nothing, gracefully}.
Te permite hacer esto:
echo ${var:=something or other}
echo $var
something or other
something or other
AQUÍ-DOCUMENTOS
Y, por cierto, la definición en línea de una variable nula o sin definir también es la razón por la que funciona lo siguiente:
<<HEREDOC echo $yo
${yo=yoyo}
HEREDOC
yoyo
La mejor manera de pensar en un here-document
es como un archivo real transmitido a un descriptor de archivo de entrada. Más o menos eso es lo que son, pero diferentes shells los implementan de manera ligeramente diferente.
En cualquier caso, si no cita el <<LIMITER
flujo, lo transfiere y lo evalúa. Por lo expansion.
tanto, declarar una variable en un here-document
puede funcionar, pero solo a través de lo expansion
cual lo limita a establecer solo variables que aún no están establecidas. Aún así, eso se adapta perfectamente a sus necesidades tal como las describió, ya que sus valores predeterminados siempre se establecerán cuando llame a la función de impresión de su plantilla.
POR QUÉ NO eval?
Bueno, el ejemplo que he presentado proporciona un medio seguro y efectivo de aceptar. parameters.
Debido a que maneja el alcance, cada variable dentro de set via ${parameter:=expansion}
se puede definir desde afuera. Entonces, si pones todo esto en un script llamado template_pr.sh y ejecutas:
% RESULT=something_else template_pr.sh
Obtendrías:
Fui a la casa de tu madre y vi Disney on Ice
Si haces caligrafía, harás algo
Fui al cementerio y vi Disney on Ice
Si haces matemáticas correctivas, harás algo
Fui al cementerio y vi Disney on Ice
Si haces matemáticas correctivas, harás algo
Esto no funcionaría para aquellas variables que se configuraron literalmente en el script, como $EVENT, $ACTION,
y$one,
pero solo las definí de esa manera para demostrar la diferencia.
En cualquier caso, la aceptación de una entrada desconocida en una evaled
declaración es inherentemente insegura, mientras que parameter expansion
está específicamente diseñada para hacerlo.