Cómo restar filas (líneas) con AWK

9

Estoy tratando de descubrir cómo puedo usar AWK para restar líneas. Por ejemplo, imagine que el archivo de entrada es:

30
20

El resultado sería:

10

Ahora, como prueba, intento calcular la columna de memoria "Usado" a partir de:

$ cat /proc/meminfo

Así que en este momento he escrito esto:

$ grep -P 'MemTotal|MemFree' /proc/meminfo | \
    -- Here comes the calculation using AWK

He probado lo siguiente:

$ grep -P 'MemTotal|MemFree' /proc/meminfo | \
    awk '{print $2}' | awk '{$0-s}{s=$0} END {print s}' 

Pero esto solo me da la última fila de datos.

He encontrado una solución que funciona, pero dudo que sea la más óptima. Toda mi experiencia en codificación me dice que la codificación dura de la cantidad de filas es terrible: P

$ grep -P 'MemTotal|MemFree' /proc/meminfo | \
    awk '{print $2}' | awk 'NR == 1{s=$0} NR == 2 {s=s-$0} END {print s}'
Dylan Meeus
fuente
¿Qué te gustaría hacer con N filas? ¿Debería ser el resultado final line1_$2 - line2_$2 - lineN-$2? ¿Solo quieres restar las dos primeras filas consecutivas?
terdon

Respuestas:

9

También puede hacer esto utilizando awk, pastey bc. Encuentro este enfoque más fácil de recordar, la sintaxis de awksiempre requiere que busque cosas para confirmar.

NOTA: Este enfoque tiene la ventaja de poder competir con múltiples líneas de salida, restando los números 2º, 3º, 4º, etc. del 1º.

$ grep -P 'MemTotal|MemFree' /proc/meminfo | \
    awk '{print $2}' | paste -sd- - | bc
7513404

Detalles

Lo anterior se utiliza awkpara seleccionar la columna que contiene los números que queremos restar.

$ grep -P 'MemTotal|MemFree' /proc/meminfo | \
    awk '{print $2}'
7969084
408432

Luego usamos pastepara combinar estos valores de 2 valores y agregar el signo menos entre ellos.

$ grep -P 'MemTotal|MemFree' /proc/meminfo | \
    awk '{print $2}'| paste -sd- -
7969084-346660

Cuando le pasamos esto bc, realiza el cálculo.

$ grep -P 'MemTotal|MemFree' /proc/meminfo | \
    awk '{print $2}'| paste -sd- - | bc
7513404
slm
fuente
@terdon - gracias estaba haciendo esa edición cuando lo hiciste 8-)
slm
3

La solución puramente awk, sin comandos cat o grep redundantes:

awk '/MemTotal/ {TOT=$2} /MemFree/ {FREE=$2} END {printf("%d kB Used\n", TOT-FREE)}' /proc/meminfo

Veo que awk_FTW me ganó, pero pensé que formatear la salida podría ser agradable.

Johan
fuente
3

Prueba esto:

grep -P 'MemTotal|MemFree' /proc/meminfo | \
awk 'NR==1{s=$2;next}{s-=$2}END{print s}'
Cuonglm
fuente