# How to subtract rows (lines) with AWK

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, 2014 at 16:55

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, 2014 at 17:00

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.

• Excellent! I love it. Thanks a lot
– arif
Sep 3, 2020 at 15:30

Try this:

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