Home > Software engineering >  Subtracting the values in two rows using Awk
Subtracting the values in two rows using Awk

Time:11-02

I’m new to awk and I’m trying to learn bash on my own, I find awk really interesting and I’m just wondering how I would subtract the values of two rows

34 43 67 87
21 22 64 43

such that I reach a desired output of

13 21 3 44

my attempt at it

awk 'BEGIN{ FS = "\n" }{avgShirts=$1-$2}{print avgShirts}'

Since its only two rows I tried by specifying that the field seperator is a new line but it didnt work.

CodePudding user response:

Assumptions/understanding:

  • input consists of exactly 2 rows
  • both rows have the same number of fields/columns

Input:

$ cat 2rows.dat
34 43 67 87
21 22 64 43

One awk idea:

awk '
NR==1 { for (i=1;i<=NF;i  )            # 1st line, loop through each field and ...
            fld[i]=$i                  # store each field in array fld[]
        next                           # skip the rest of the awk script and proceed to the next input line
      }
      { for (i=1;i<=NF;i  ) {          # 2nd line, loop through each field and ...
            line=line pfx (fld[i]-$i)  # build output line based on difference of fields from 1st and 2nd lines
            pfx=OFS                    # 1st pass through loop pfx="", rest of loop pfx=" "
        }
        print line                     # print line of differences
      }
' 2rows.dat

This generates:

13 21 3 44

An alternate awk idea that prints the sums as they're calculated:

awk '
NR==1 { for (i=1;i<=NF;i  )
            fld[i]=$i
        next
      }
      { for (i=1;i<=NF;i  ) {
            printf "%s%s", pfx, (fld[i]-$i)   # print prefix and current diff, since there is no "\n" we remain on the same output line for the next pass through the loop
            pfx=OFS
        }
        print ""                              # terminate line; same effect as: printf "\n"
      }
' 2rows.dat

This also generates:

13 21 3 44

CodePudding user response:

You can do:

awk 'FNR%2{for (i=1;i<=NF;i  ) arr[i]=$i; next}
     {for (i=1;i<=NF;i  ) $i=arr[i]-$i} 1' file
13 21 3 44

Explanation:

# save every odd line 
FNR%2{for (i=1;i<=NF;i  ) arr[i]=$i; next}

# every even line, subtract this field from the previous and print 
{for (i=1;i<=NF;i  ) $i=arr[i]-$i} 1'

CodePudding user response:

$ awk '
    NR==1 { split($0,minuends); next }
    {
        for (i=1; i<=NF; i  ) {
            printf "%d%s", minuends[i] - $i, (i<NF ? OFS : ORS)
        }
    }
' file
13 21 3 44

If you're new to awk then look up NR, NF, OFS, ORS, and split() in the man page. You can learn awk from the book Effective AWK Programming, 5th Edition, by Arnold Robbins.

  • Related