Tengo la siguiente función recursiva para establecer variables de entorno:
function par_set {
PAR=$1
VAL=$2
if [ "" != "$1" ]
then
export ${PAR}=${VAL}
echo ${PAR}=${VAL}
shift
shift
par_set $*
fi
}
Si lo llamo solo, establece la variable y hace eco en stdout:
$ par_set FN WORKS
FN=WORKS
$ echo "FN = "$FN
FN = WORKS
Redirigir stdout a un archivo también funciona:
$ par_set REDIR WORKS > out
cat out
REDIR=WORKS
$ echo "REDIR = "$REDIR
REDIR = WORKS
Pero, si canalizo stdout a otro comando, la variable no se establece:
$ par_set PIPE FAILS |sed -e's/FAILS/BARFS/'
PIPE=BARFS
$ echo "PIPE = "$PIPE
PIPE =
¿Por qué la tubería impide que la función exporte la variable? ¿Hay alguna manera de solucionar esto sin recurrir a archivos temporales o canalizaciones con nombre?
Resuelto:
Código de trabajo gracias a Gilles:
par_set $(echo $*|tr '=' ' ') > >(sed -e's/^/ /' >> ${LOG})
Esto permite que el script se llame así:
$ . ./script.sh PROCESS_SUB ROCKS PIPELINES=NOGOOD
$ echo $PROCESS_SUB
ROCKS
$ echo $PIPELINES
NOGOOD
$ cat log
7:20140606155622162731431:script.sh:29581:Parse Command Line parameters. Params must be in matched pairs separated by one or more '=' or ' '.
PROCESS_SUB=ROCKS
PIPELINES=NOGOOD
Proyecto alojado en bitbucket https://bitbucket.org/adalby/monitor-bash si está interesado en el código completo.
Esto no funciona porque cada lado de la tubería se ejecuta en una subshell
bash
, y las variables establecidas en una subshell son locales para esa subshell.Actualizar:
Parece que es fácil pasar variables del shell principal al secundario, pero es realmente difícil hacerlo de la otra manera. Algunas soluciones se denominan canalizaciones, archivos temporales, escritura en stdout y lectura en el padre, etc.
Algunas referencias:
http://mywiki.wooledge.org/BashFAQ/024
/programming//q/15541321/3565972
/programming//a/15383353/3565972
http://forums.opensuse.org/showthread .php / 458979-How-export-variable-in-subshell-back-out-to-parent
fuente
$$
es lo mismo para los caparazones de padres e hijos. Puede usar$BASHPID
para obtener la subshell pid. Cuando en miecho $$ $BASHPID
interiorpar_set
obtengo diferentes pids.Señala las subcapas, que se pueden solucionar con algunos cambios en el caparazón fuera de una tubería, pero la parte más difícil del problema tiene que ver con la concurrencia de la tubería .
Todos los miembros del proceso de la tubería comienzan a la vez , por lo que el problema podría ser más fácil de entender si lo mira así:
Los procesos de canalización no pueden heredar los valores de las variables porque ya están desactivados y ejecutándose antes de que la variable se establezca.
Realmente no puedo entender cuál es el punto de su función: ¿para qué sirve que
export
ya no sirve? O incluso solovar=val
? Por ejemplo, aquí está casi la misma tubería nuevamente:Y con
export
:Entonces tu cosa podría funcionar así:
Lo cual se registraría en
sed
la salida de un archivo y lo entregaría a su función como una división de shell"$@"
.O alternativamente:
Sin embargo, si fuera a escribir su función, probablemente se vería así:
fuente
|pipeline | sh
sh
. El ya esta usandoexport
.