Como subtrair linhas (linhas) com AWK

9

Estou tentando descobrir como posso usar o AWK para subtrair linhas. Por exemplo, imagine que o arquivo de entrada seja:

30
20

A saída seria:

10

Agora, como teste, estou tentando calcular a coluna de memória "Usado" em:

$ cat /proc/meminfo

Então, no momento eu escrevi isso:

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

Eu tentei o seguinte:

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

Mas isso me dá a última linha de dados.

Encontrei uma solução funcional, mas duvido que seja a mais ideal. Toda a minha experiência em codificação me diz que a codificação embutida da quantidade de linhas é terrível: 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
fonte
O que você gostaria de fazer com N linhas? O resultado final deve ser line1_$2 - line2_$2 - lineN-$2? Deseja apenas subtrair as duas primeiras linhas consecutivas?
terdon

Respostas:

9

Você também pode fazer isso usando awk, pastee bc. Acho essa abordagem mais fácil de lembrar, a sintaxe de awksempre exige que eu procure as coisas para confirmar.

NOTA: Essa abordagem tem a vantagem de poder lidar com várias linhas de saída, subtraindo os números 2, 3, 4, etc. do 1 º.

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

Detalhes

O descrito acima usa awkpara selecionar a coluna que contém os números que queremos subtrair.

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

Em seguida, usamos pastepara combinar esses dois valores e adicionar o sinal de menos entre eles.

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

Quando passamos isso para bcele, realiza o cálculo.

$ grep -P 'MemTotal|MemFree' /proc/meminfo | \
    awk '{print $2}'| paste -sd- - | bc
7513404
slm
fonte
@terdon - graças eu estava fazendo isso edição quando você fez isso 8-)
SLM
3

A solução puramente awk, sem comandos redundantes de gato ou grep:

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

Vejo awk_FTW me superando, mas apesar de formatar a saída, pode ser bom.

Johan
fonte
3

Tente o seguinte:

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