Tengo un archivo de datos que quiero normalizar usando awk
, basado en el último punto de datos. Por lo tanto, me gustaría acceder primero al último punto de datos, para normalizar los datos y luego procesarlos normalmente.
El siguiente método, usando tac
dos veces, hace el trabajo, pero es quizás más complicado de lo necesario.
$ cat file
0 5
1 2
2 3
3 4
$ tac file | awk 'NR==1{norm=$2} {print $1, $2/norm}' | tac
0 1.25
1 0.5
2 0.75
3 1
Mi pregunta es la siguiente: ¿Es posible obtener el resultado anterior usando solo awk?
Creo que la respuesta es "No, awk escanea el archivo línea por línea", pero estoy abierto a sugerencias de alternativas.
fuente
$ awk --version GNU Awk 3.1.8
. ¿Puede agregar una explicación muy pequeña sobre cómo se manejan dos archivos de entrada y quénext
hace?Si su fuente de datos es un archivo que se puede leer varias veces (es decir, no es una secuencia), primero debe usar
tail(1)
para obtener los datos que desea de la última línea y pasarlos a awk para su procesamiento secuencial del archivo.tail
buscará hasta el final del archivo para leer la última línea sin necesidad de leer todos los datos anteriores.Esto será una gran victoria en archivos grandes donde el archivo completo no cabe en la memoria caché del búfer (lo que significa que debería leerse desde el disco dos veces, una vez por cada pasada), y ayudará en menor medida al no tener que escanear la entrada para llegar a la última línea. Los archivos más pequeños pueden no mostrar mucha diferencia con un enfoque de dos pasos.
fuente
Puede cargarlos en una matriz y leerlo al revés:
Podría hacerlo de manera más eficiente, pero este tipo de ilustración ilustra por qué
awk
no es la herramienta adecuada para esto. Continúe usandotac
donde esté disponible, GNU tac es generalmente el más rápido de una variedad de herramientas para este trabajo.fuente
for
-loops inawk
no es la solución.