Home > Software engineering >  Backtracking with the awk (GNU) command
Backtracking with the awk (GNU) command

Time:02-18

Say one of your data files returns you all their readings. After removing all the clutter; you obtain, with always 3 columns:

-ERROR -1.57 -2.02 
-2.10 -0.57 ERROR
-4.70 ERROR -0.52 
-2.20 ERROR -0.02 
-2.20 -0.07 ERROR

I know ERROR is the only error message and happens for any data at random, and is, therefore, the only value that isn't a number.

THE CHALLENGE

How can I replace any invalid reading with the last successful one? I've tried

awk -F' ' ' {if (isNumber $1){ replace with previous $1}}' < log.data

But how do you reference the previous reading to begin with?

Expected output:

 0 -1.57 -2.02 
-2.10 -0.57 -2.02
-4.70 -0.57 -0.52 
-2.20 -0.57 -0.02 
-2.20 -0.07 -0.02

CodePudding user response:

Assumptions:

  • all rows have the same number of space-delimted fields/columns
  • all non-numeric values contain the literal string ERROR
  • if first row contains a non-numeric value then the replacement value will be zero (0)

One awk idea:

awk '
{ for (i=1;i<=NF;i  ) {     # loop through fields
      if ($i ~ "ERROR")     # if problematic value found then ...
         $i=last[i] 0       # replace with the last value seen; " 0" to force undefined to be zero (and not "")
      last[i]=$i            # save current field as "last" for the next input line
  }
  print $0                  # print current line
}
' log.data

This generates:

0 -1.57 -2.02
-2.10 -0.57 -2.02
-4.70 -0.57 -0.52
-2.20 -0.57 -0.02
-2.20 -0.07 -0.02

CodePudding user response:

You may use this awk:

awk '{
   for (i=1; i<=NF;   i) {
      if ($i 0 != $i)
         $i = prev[i] 0
      prev[i]=$i
   }
} 1' file

0 -1.57 -2.02
-2.10 -0.57 -2.02
-4.70 -0.57 -0.52
-2.20 -0.57 -0.02
-2.20 -0.07 -0.02

$i 0 != $i will return true if $i is non-numeric value.

  • Related