9

I'm trying to figure out how I can use AWK to subtract lines. For example, imagine the input file is:

30
20

The output would be:

10

Now, as a test I am trying to calculate the "Used" memory column from:

$ cat /proc/meminfo

So at the moment I have written this:

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

I have tried the following:

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

But this just gives me the last row of data.

I've found a working solution, but I doubt it's the most optimal one. All my coding experience tells me that hard coding the amount of rows is terrible :P

$ grep -P 'MemTotal|MemFree' /proc/meminfo | \
    awk '{print $2}' | awk 'NR == 1{s=$0} NR == 2 {s=s-$0} END {print s}'
  • What would you want done with N rows? Should the final result be line1_$2 - line2_$2 - lineN-$2? Do you only want to subtract the first two consecutive rows? – terdon Mar 2 '14 at 16:55
9

You can also do this using awk, paste, and bc. I find this approach easier to remember, the syntax of awk always requires me to look things up to confirm.

NOTE: This approach has the advantage of being able to contend with multiple lines of output, subtracting the 2nd, 3rd, 4th, etc. numbers from the 1st.

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

Details

The above uses awk to select the column that contains the numbers we want to subtract.

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

We then use paste to combine these 2 values values and add the minus sign in between them.

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

When we pass this to bc it performs the calculation.

$ grep -P 'MemTotal|MemFree' /proc/meminfo | \
    awk '{print $2}'| paste -sd- - | bc
7513404
  • @terdon - thanks I was making that edit when you did it 8-) – slm Mar 2 '14 at 17:00
3

The purely awk solution, no redundant cat or grep commands:

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

I see awk_FTW beat me to it but I though formatting the output could be nice.

3

Try this:

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.