row sum with awk followed by a transformation

Viewed 50

I have this:

.2 .5
.1 .1
.3 .3

I want two columns of results:

one column for the sum of each row

second column for 1 - the sum of each row when the sum is greater than .5

.7 .3
.2 .2
.6 .4

I know how to get the row sum column:

awk '{for(i=1;i<=NF;i++) t+=$i; print t; t=0}'

not sure how to get the second column (in the same awk one liner if possible)

Any advice is greatly appreciated, thank you!

3 Answers

If you just have 2 columns, you can sum both first. And for the second column print 1 - sum if the sum itself is greater than 0.5.

Else you print the sum.

awk '{
  sum = $1 + $2
  print sum, (sum > 0.5 ? 1 - sum : sum)
}' file

Output

0.7 0.3
0.2 0.2
0.6 0.4

If you want to remove the leading zeros, you might use gnu-awk with gensub and capture the FS and the optional minus sign with a regex and 2 capture groups:

awk '{
  sum = $1 + $2
  print gensub(/(^|[[:space:]]+)(-?)0+/,
    "\\1\\2",
    "g",
    sum FS (sum > 0.5 ? 1 - sum : sum))
}' file

Output

.7 .3
.2 .2
.6 .4

Adding a couple lines to the input file:

$ cat file
.2 .5
.1 .1
.3 .3
11.3 .3
1.3 .3

One awk idea using a conditional (aka ternary) expression to determine the 2nd output column:

$ awk '{t=0; for(i=1;i<=NF;i++) t+=$i; print t, (t>0.5 ? 1-t : t)}' file
0.7 0.3
0.2 0.2
0.6 0.4
11.6 -10.6
1.6 -0.6

If the leading 0's need to be removed, one brute force idea:

$ awk '{ t=0;
         for(i=1;i<=NF;i++) t+=$i
         out=t OFS (t>.5 ? 1-t : t) 
         gsub(/^0./,".",out)
         gsub(/-0./,"-.",out)
         gsub(/ 0./," .",out) 
         print out
       }' file
.7 .3
.2 .2
.6 .4
11.6 -10.6
1.6 -.6

Or if you have GNU awk (for the \< word boundary flag):

$ awk '{ t=0;
         for(i=1;i<=NF;i++) t+=$i
         out=t OFS (t>.5 ? 1-t : t)
         gsub(/\<0./,".",out)
         print out
       }' file
.7 .3
.2 .2
.6 .4
11.6 -10.6
1.6 -.6

Or if you don't mind spawning a subprocess ... adding karakfa's sed suggestion:

$ awk '{t=0; for(i=1;i<=NF;i++) t+=$i; print t, (t>0.5 ? 1-t : t)}' file | sed 's/\b0\././g'
.7 .3
.2 .2
.6 .4
11.6 -10.6
1.6 -.6
{m,g,n}awk 'BEGIN { OFMT = "%."(_^=_<_) "f" (__="")
                    ____ = "["(___=".") "]"
} ($NF = (($_ += $NF) + $_)<_ ? $_ : _-$_)^__^gsub((!_)____, ___)'
.7 .3
.2 .2
.6 .4
Related