2012-08-16 23 views
5

primer mensaje aquí, pero ha sido un acertijo durante siglos. he buscado en Google por edades, pero no puedo encontrar lo que quiero (muchos temas de temas abigarrados que no solicitan lo que el tema sugiere que haga ...). no es nuevo para awk o scripting, solo un poco oxidado :)awk: configuración de las variables de entorno directamente desde dentro de una secuencia de comandos awk

Estoy tratando de escribir un script awk que establecerá valores de env del intérprete mientras se ejecuta - para otro script bash para recoger y utilizar más adelante. simplemente no puedo usar stdout de awk para informar este valor que quiero configurar (es decir, "exportar lo que sea = awk cmd here"), ya que eso está dirigido a un 'archivo de resultados' creado por awkscript (además tengo más de una variable para exportar el código final de todos modos).

Como un script de prueba ejemplo, a Demo mi problema:

echo $MYSCRIPT_RESULT   # returns nothing, not currently set 
echo | awk -f scriptfile.awk # do whatever, setting MYSCRIPT_RESULT as we go 
echo $MYSCRIPT_RESULT   # desired: returns the env value set in scriptfile.awk 

dentro scriptfile.awk, he intentado (sin éxito)

1 /) construir y ejecutar una cadena adhoc directamente:

{ 
    cmdline="export MYSCRIPT_RESULT=1" 
    cmdline 
} 

2 /) usando la función de sistema:

{ 
    cmdline="export MYSCRIPT_RESULT=1" 
    system(cmdline) 
} 

... pero estos no funcionan. Sospecho que estos 2 comandos están creando una subshell dentro del shell desde el que se está ejecutando awk y haciendo lo que solicité (probado al tocar archivos como una prueba), pero una vez que las llamadas al sistema/cmd se han completado, la subshell muere, desafortunadamente tomando lo que sea que haya establecido con él, por lo que los cambios en mi env no se adhieren a la perspectiva del "que llama del awk".

así que mi pregunta es, ¿cómo se configuran las variables de env dentro de awk directamente, para que un proceso de llamada pueda acceder a estos valores env después de que se complete la ejecución awk? ¿es realmente posible?

aparte de las formas de adhoc/system anteriores, que he demostrado que no funciona, no puedo ver cómo se podría hacer esto (aparte de escribir estos valores en un archivo "aleatorio" en algún lugar para ser recogido y leído por invocando script, que de todos modos está un poco sucio), ¡por lo tanto, ayuda!

todas las ideas/sugerencias/comentarios son bienvenidos!

+0

no se puede hacer. esta es una regla básica de los entornos de SO, los procesos secundarios pueden cambiar ** su ** entorno pero no el entorno de sus padres. Lo mejor que puede hacer es, (a partir de un script de shell) 'myParentVar = $ (echo" $ myParentVar "| awk '{sub (/ xxxx /," yyyy ", $ 0); print $ 0}')' (donde 'sub (...) 'es un marcador de posición para cualquier modificación que desee realizar en $ myParetntVar. Buena suerte. – shellter

+0

thx por la respuesta. yo estaba affraid que esto iba a ser el caso (padre/configuración env infantil y ámbito de influencia), así que creo que voy a tener que ir con un archivo de ensayo para estas variables env para la escritura del golpe de llamada para el acceso. THX para confirmar lo que creía que de todos modos :( – user1603289

+0

que tenía un problema con esto también. lo que hice fue escribir la salida de awk a un archivo temporal y luego proceden del archivo temporal. Funciona. No estoy seguro si es elegante pero sigue siendo muy unixy. – qodeninja

Respuesta

4

No puede cambiar el entorno de su proceso principal. Si

MYVAR=`awk stuff` 

es inaceptable, lo que está pidiendo no se puede hacer.

+0

Como la explicación anterior, tiene usted razón en que yo estoy tratando de ajustar el env padres del niño, que es un no-no (no lo pensé de esta manera cuando publiqué). Esto deja 2 formas de avanzar: realice el retorno de awk (stdout) el resultado que busca, o si eso no es posible (como yo mismo) informe estos valores en un archivo de texto, que luego el padre puede examinar para obtener los valores que está tratando de volver atrás (en mi caso, use una variable env para decirle a awk dónde está este "archivo de actualización" (usando mktemp), haciendo las cosas un poco más limpias en el código/implementación :)). – user1603289

2

Puede hacer esto, pero es un poco complicado. Desde awk no permite la redirección a un descriptor de archivo, se puede utilizar un FIFO o un archivo normal:

$ mkfifo fifo 
$ echo MYSCRIPT_RESULT=1 | awk '{ print > "fifo" }' & 
$ IFS== read var value < fifo 
$ eval export $var=$value 

En realidad no es necesario dividir el var y el valor; usted podría simplemente tener awk imprimir la "exportación" y simplemente evaluar la salida directamente.

+0

En 'gawk' puede enviar a un descriptor de archivo alternativo que se abrió en el shell primario. Como alternativa, si 'stderr' no se usa, se podría usar como una forma de generar el valor. –

+0

la FIFO es una idea interesante, sin embargo existe la posibilidad (no siempre lo es) que el comando awk podría no devolver nada (condiciones de error), que entonces la ejecución bloques en la lectura FIFO (el guión awk no es un chiste - mucho ¡de eso!). También me gusta la idea de usar stderr, sin embargo stderr debe mantenerse "sin código" para esos momentos si/cuando falla el script, ya que no queremos introducir gibber en el programa en tiempo de ejecución, por lo tanto, no creo que sea una buena idea para usar cualquiera de los dos, pero gracias de todos modos (dije que todas las ideas eran bienvenidas) - he ido con tempfiles, es un poco más seguro – user1603289

+0

hasta hoy nunca había escuchado de mkfifo. ¡Gracias! mkfifo + nc = ¡sí! – qodeninja

1

También puede usar algo como se describe en Set variable in current shell from awk

unset var 
var=99 
declare $(echo "foobar" | awk '/foo/ {tmp="17"} END {print "var="tmp}') 
echo "var=$var" 
var= 

La cláusula awk FIN es esencial de lo contrario, si no hay coincidencias con el patrón de declarar vuelca el entorno actual a la salida estándar y no cambia el contenido de tu variable.

valores múltiples se pueden configurar separándolas con espacios.

declare a=1 b=2 
echo -e "a=$a\nb=$b" 

NOTA: declare is bash only, para otras shells, use eval con la misma sintaxis.

Cuestiones relacionadas