2009-12-25 13 views
33

Deseo ejecutar el comando system en un script awk y obtener su salida almacenada en una variable. He intentado hacer esto, pero la salida del comando siempre va al shell y no puedo capturarlo. ¿Alguna idea sobre cómo se puede hacer esto?Asignación de la salida del comando del sistema a la variable

Ejemplo:

$ date | awk --field-separator=! {$1 = system("strip $1"); /*more processing*/} 

debe llamar al comando strip sistema y en lugar de enviar la salida a la cáscara, debe asignar la salida de nuevo a $1 para más procesamiento. Rignt ahora, está enviando salida al shell y asignando el retcode del comando al $1.

+1

nit: La salida no va a la cáscara, que va al terminal /consola. El shell no lee ninguno de los resultados de sus hijos, solo comparten los descriptores de archivos que están asociados con el mismo tty. –

Respuesta

23

Calculado.

Utilizamos de awk Two-way I/O

{ 
    "strip $1" |& getline $1 
} 

pasa $ 1 a desnudarse y la getline toma de salida de la tira de vuelta $ 1

+1

Si necesita llamar al mismo comando varias veces, debemos cerrar el comando (http://www.staff.science.uu.nl/~oostr102/docs/nawk/nawk_26.html#SEC29) – mcoolive

49

Nota: coproceso es GNU awk específica. De todos modos otra alternativa es usar getline

cmd = "strip "$1 
while ((cmd | getline result) > 0) { 
    print result 
} 
close(cmd) 
+0

Gracias. De esta manera, puedo eliminar el & de mi respuesta. Parece más fresco. Pero solo estoy escribiendo para Linux, por lo que la indisponibilidad de Gawk no debería ser un problema. – Sahas

+0

sí, no debería ser un problema. aún debe verificar la documentación y ver si el coproceso solo está disponible en cierta versión de gawk. No puedo recordar en la parte superior de mi cabeza – ghostdog74

+0

De la versión 3.1. RedHat tiene 3.1.5. De todos modos, usaré la forma que sugirió, a menos que desee enviar algo al comando de comando, en cuyo caso el coproceso es útil. – Sahas

5
gawk '{dt=substr($4,2,11); gsub(/\//," ",dt); "date -d \""dt"\" +%s"|getline ts; print ts}' 
+13

Si publica respuestas, debe explicar las diferentes partes (lo que hizo y por qué funciona). Para que otros puedan aprender de tu respuesta. Para algunas personas esta línea sería auto explicativa. Pero para otros es difícil seguir lo que hiciste exactamente. –

16

Para ejecutar un comando del sistema en awk se puede utilizar system() o cmd | getline.

prefiero cmd | getline, ya que le permite ponerse al valor en una variable:

$ awk 'BEGIN {"date" | getline mydate; close("date"); print "returns", mydate}' 
returns Thu Jul 28 10:16:55 CEST 2016 

De manera más general, se puede establecer el comando en una variable:

awk 'BEGIN { 
     cmd = "date -j -f %s" 
     cmd | getline mydate 
     close(cmd) 
    }' 

Nota es importante use close() para evitar que aparezca un error "hace demasiados archivos abiertos" si tiene resultados múltiples (gracias mateuscb para señalar esto en los comentarios).


Usando system(), la salida del comando se imprime de forma automática y el valor que puede tomar es su código de retorno:

$ awk 'BEGIN {d=system("date"); print "returns", d}' 
Thu Jul 28 10:16:12 CEST 2016 
returns 0 
$ awk 'BEGIN {d=system("ls -l asdfasdfasd"); print "returns", d}' 
ls: cannot access asdfasdfasd: No such file or directory 
returns 2 
+2

+1 para agregar 'close()', si no lo agrega y tiene varios resultados, puede obtener "hace demasiados archivos abiertos". Si tiene un comando más largo, puede hacer 'cmd =" ​​date -j -f% s "; cmd | getline mydate; close (cmd) ' – mateuscb

+1

@mateuscb muchas gracias por su comentario. Actualicé la pregunta para incluir tus comentarios útiles. – fedorqui

+1

Gracias por recordar el comando close(). Esto ayuda mucho. Sin poner close(), a veces obtengo un resultado de fecha incorrecto para obtener resultados múltiples. Con poner cerca(). mis múltiples resultados de fecha se muestran correctamente. – csu007

Cuestiones relacionadas