Tengo este siguiente script awk
que toma el siguiente archivo de entrada, input.txt
y produce la salida a continuación. ¿Alguien puede tomarse el tiempo para analizar cómo funciona este awk
? Le he dedicado un poco de tiempo y no tiene mucho sentido.
Entrada:
$ cat input.txt
FINISHED RSYNCJOBNA 20140502 0021 2182096 2082096 6 5 2014820905820902 10:02:15 2014820905820902 10:56:42 0:54:27 INITIATED RSYNCJOBNA 20140502 0022 3282096 3182096 6 5 2014820905820902 15:31:06 0:06:04 ce eque**
Salida:
RSYNCJOBNA|0021|20140502|10:02:15|10:56:42|0:54:27|FINISHED RSYNCJOBNA|0022|20140502|15:31:06| |0:06:04|INITIATED
Comando para obtener la salida anterior:
awk -v OFS="|" "/FINISHED|INITIATED/ { status = $1; getline; jobname = $1; getline; sequence = $2; date = $1; getline; start = $2; getline; if (status == "FINISHED") { end = $2; getline } else { end = " " } runtime = $1; print jobname, sequence, date, start, end, runtime, status; }" input.txt
Tengo entendido que /FINISHED|INITIATED/ {}
significa que los comandos dentro de las llaves solo se ejecutarán en líneas que coincidan con FINISHED
o INITIATED
Por lo que puedo decir de la salida, el script parece estar analizando desde todas líneas. ¿Qué está pasando?
Comentarios
Respuesta
La función getline
lee la siguiente línea y mueve el script a ella. Entonces, getline
llamadas consecutivas pasan a la siguiente línea. Esto es quizás más fácil de entender con un ejemplo:
$ cat input.txt foo 1 2 $ awk "/foo/{print; getline; print; getline; print}" input.txt foo 1 2
Como como puede ver arriba, el script procesará la primera línea porque coincide con foo
. Cada llamada a getline
leerá la línea después de la actual, por lo que las siguientes llamadas print
imprimen las siguientes líneas.
Respuesta
Si no «sabe lo que hace una función awk
, la estrategia habitual es para echar un vistazo a la página del manual:
getline
Establecer $ 0 desde el siguiente registro de entrada; establecer NF, NR, FNR, RT
De hecho, el bloque de comandos se ejecuta solo dos veces. Las otras líneas se manejan a través de getline
desde dentro del bloque.
Esto podría reescribirse a:
/FINISHED|INITIATED/ { status = $1; line_number=0; next; } { line_number++; } line_number==1 { jobname = $1; } line_number==2 { sequence = $2; date = $1; } ...
Comentarios
- ¿Qué sucede si el siguiente registro está vacío?
- @AvinashRaj Ni tu código ni mi alternativa miran el contenido de las líneas (con la excepción de
/FINISHED|INITIATED/
). Las líneas simplemente se cuentan hacia atrás. Los datos deben estar ordenados exactamente (de un awk parsi ng perspectiva) de la forma que ha mostrado, de lo contrario el código se romperá.
/FINISHED|INITIATED/
, awk busca la línea correspondiente y realiza la operación solo en esa línea en particular. Pero la operación se realizó en todas las líneas. ¿Cómo?