Keeping float value decimal places in an awk script

Viewed 104

I have this line using awk:

$ awk '{
                 for (i=1;i<=NF;i++){
                   if ($i+0 != $i)
                     $i = temp[i]+0.00
                   temp[i]=$i+0.00
                }}1'

In short, this converts every word to the last seen number of that column.

THE PROBLEM

The issue is that the decimals place of every value that comes out of $i = temp[i]+0.00 loses its decimals precision.

For example,

-ERROR -1.57 -2.02 
-2.10 2.70 ERROR
-4.70 ERROR -0.52 
-2.20 ERROR -0.02 
-2.20 -1.50 ERROR

Turns into:

0 -1.57 -2.02 
-2.10 2.70 -2.02
-4.70 2.7 -0.52 
-2.20 2.7 -0.02 
-2.20 -1.50 -0.02

2.70 would become 2.7 and so every word that directly follows 2.70 would not be turned into 2.70, but instead into 2.7. How can you force awk to save a float value to a set amount of decimal places?

Obviously, +0.00 didn't help.

2 Answers

Refrain from performing math on the values which in turn disables awk from making decisions on how many digits of accuracy to maintain; instead, just save each value as is (effectively save as a string).

Consider:

$ printf "1 1.1 1.02 1.003 1.0004 1.00005\na b c d e f\n" 
1 1.1 1.02 1.003 1.0004 1.00005
a b c d e f

A few tweaks to OP's current awk code:

$ printf "1 1.1 1.02 1.003 1.0004 1.00005\na b c d e f\n" | awk '
{ for (i=1;i<=NF;i++){
      if ($i+0 != $i)
         $i = (i in temp ? temp[i] : 0)
      temp[i]=$i
   }
} 1'
1 1.1 1.02 1.003 1.0004 1.00005
1 1.1 1.02 1.003 1.0004 1.00005

Coming back to OP's sample data ...

Adding some more lines to the sample data set:

$ cat sample.dat
-ERROR -1.57 -2.02
-2.10 2.70 ERROR
-4.70 ERROR -0.52
-2.20 ERROR -0.02
-2.20 -1.50 ERROR
-3.333 0.1234 -0.02
ERROR ERROR ERROR
-2.10 2.70 ERROR
-4.70 ERROR -0.52

Running the modified awk code:

awk '
{ for (i=1;i<=NF;i++){
      if ($i+0 != $i)
         $i = (i in temp ? temp[i] : 0)
      temp[i]=$i
   }
}1' sample.dat

This generates:

0 -1.57 -2.02
-2.10 2.70 -2.02
-4.70 2.70 -0.52
-2.20 2.70 -0.02
-2.20 -1.50 -0.02
-3.333 0.1234 -0.02
-3.333 0.1234 -0.02
-2.10 2.70 -0.02
-4.70 2.70 -0.52

If this doesn't address the issue then we'll need to see more sample data that more accurately reproduces the issue.

With your shown samples, please try following awk code.

awk '
{
  val=""
  for(i=1;i<=NF;i++){
    if(int($i)){
      val=(val?val OFS:"") $i
      arr[i]=$i
    }
    else{
      val=(val?val OFS:"") (i in arr?arr[i]:0)
    }
  }
  print val
}
'  Input_file
Related