opciones - bash: ¿Cómo creo una función desde una variable?
substr linux bash (5)
De hecho, es instructivo que la construcción antes mencionada haga descarrilar la posibilidad de tener comillas incrustadas en su interior y, por lo tanto, sea potencialmente rebelde. Sin embargo, la siguiente construcción ofrece una funcionalidad similar sin tener las limitaciones de la respuesta anterior.
Para su revisión:
source /dev/stdin <<EOF
function someprefix_${bname}()
{
echo "test";
};
EOF
¿Cómo creo una función nombrada desde el contenido de una variable? Quiero escribir un script de plantilla que defina una función que lleva el nombre del archivo del script. Algo como esto (que por supuesto no funciona):
#!/bin/bash
bname="$(basename $0)" # filename of the script itself
someprefix_${bname}() { # function''s name created from $bname variable
echo test
}
Entonces, si el nombre de archivo del script es foo.sh
, entonces debería definir una función llamada someprefix_foo
que hará eco de "prueba".
Las soluciones ''eval y'' source ''funcionan si IFF no tiene nada en la función que pueda evaluarse en el momento de la creación y que realmente desee retrasar hasta el tiempo de ejecución.
source /dev/stdin << EOF
badfunc ()
{
echo $(date)
}
EOF
$ date;badfunc;sleep 10;date;badfunc
Tue Dec 1 12:34:26 EST 2015 ## badfunc output not current
Tue Dec 1 12:23:51 EST 2015
Tue Dec 1 12:34:36 EST 2015 ## and not changing
Tue Dec 1 12:23:51 EST 2015
Sí, es un ejemplo artificial (solo fecha de llamada y no se hace eco de una llamada subshell), pero al usar las respuestas originales, probé algo más elaborado que requería una evaluación de tiempo de ejecución y obtuve resultados similares: evaluación en "compilación" tiempo, no correr tiempo.
La forma en que resolví el problema fue construir un archivo temporal con la función y luego obtener esa fuente. Mediante el uso juicioso de comillas simples y dobles que rodean la prueba que imprimo en el archivo, puedo controlar completamente qué se evalúa y cuándo.
tmpsh=$(mktemp)
echo "goodfunc ()" > $tmpsh
echo ''{'' >> $tmpsh
echo ''echo $(date)'' >> $tmpsh
echo ''}'' >> $tmpsh
. $tmpsh
rm -f $tmpsh
y entonces
$ date;goodfunc;sleep 10;date;goodfunc
Tue Dec 1 12:36:42 EST 2015 ## current
Tue Dec 1 12:36:42 EST 2015
Tue Dec 1 12:36:52 EST 2015 ## and advancing
Tue Dec 1 12:36:52 EST 2015
Con suerte, esto será de mayor utilidad para las personas. Disfrutar.
Puede deshabilitar la expansión de un documento aquí de esa manera:
eval "$(cat <<EOF
$function_name() {
commands go here
and "$you $do $not $have $to $escape variables"
}
EOF
)"
Ver: Cómo hacer un gato << EOF >> un archivo que contiene código?
Manual de Bash: 3.6.6 Aquí Documentos / Documento Aquí
No se realiza expansión de parámetros y variables, sustitución de comandos, expansión aritmética o expansión de nombre de archivo en word. Si se cita alguna parte de la palabra, el delimitador es el resultado de la eliminación de comillas en la palabra, y las líneas en el documento aquí no se expanden. Si la palabra no tiene comillas, todas las líneas del documento aquí están sujetas a expansión de parámetros, sustitución de comandos y expansión aritmética, la secuencia de caracteres / newline se ignora, y
/
debe utilizarse para citar los caracteres/
,$
y`
.
Puedes usar eval
:
eval "someprefix_${bname}() { echo test; }"
Bash incluso permite "."
s en nombres de funciones :)
Uso la siguiente sintaxis, que evita /dev/stdin
pero aún te permite usar heredocs:
eval "$(cat <<EOF
$function_name() {
commands go here
but "/$you /$have /$to /$escape $variables"
}
EOF
)"