Skip operation on the line if one of the columns have letters - bash

Viewed 87

I'm trying to skip operations on columns rows where End_time has the value "Failed".

Here is my actual file.

check_time.log

Done  City                               Start_time  End_time
  Yes   Chicago                            18          10
  Yes   Atlanta                            208         11
   No   Minnetonka                          57        Failed
  Yes   Hopkins                           112         80
   No   Marietta                          2018        Failed

Here is what I have so far.

awk 'BEGIN { OFS = "\t" } NR == 1 { $5 = "Time_diff" } NR >= 2 { $5 = $3 - $4 } 1' < files |column -t

Output:

  Done  City                               Start_time  End_time  Time_diff
  Yes   Chicago                            18          10        8
  Yes   Atlanta                            208         11        197
   No   Minnetonka                          57        Failed     57
  Yes   Hopkins                           112         80        32
   No   Marietta                          2018        Failed    2018

Desired output should look like this:

  Done  City                               Start_time  End_time  Time_diff
  Yes   Chicago                            18          10        8
  Yes   Atlanta                            208         11        197
   No   Minnetonka                          57        Failed 
  Yes   Hopkins                            112         80        32
   No   Marietta                          2018        Failed    

So how do I skip that?

3 Answers

You should be just able to change:

$5 = $4 - $5

into:

if ($4 != "Failed") { $5 = $3 - $4 }

This will:

  • refuse to change $5 from empty to the calculated value in lines where the end time is Failed; and
  • correctly do the calculation for all other lines.

I say correctly since it appears you want the start time minus the end time in those cases, despite the fact durations tend to be end time minus the start time. I've changed it to match your desired output rather than the "sane" expectation.

A transcript follows so you can see it in action:

pax$ awk 'BEGIN{OFS="\t"}NR==1{$5="Time_diff"}NR>=2{if($4!="Failed"){$5=$3-$4}}1' <inputFile.txt |column -t
Done  City        Start_time  End_time  Time_diff
Yes   Chicago     18          10        8
Yes   Atlanta     208         11        197
No    Minnetonka  57          Failed
Yes   Hopkins     112         80        32
No    Marietta    2018        Failed

And, just as an aside, you may want to consider what will happen when you start getting information from New York, San Antonio, Salt Lake City or, even worse, Maccagno con Pino e Veddasca :-)

Could you please try following.(Here considering that your Input_file's last fields will be this order only and will not have any other additional fields, if they have then you may need to adjust field numbers because in case your city's value is having space in it then field number from starting will create an issue in simply differentiating values for all lines because field values will be different then as per line)

awk '
FNR==1{
  print $0,"Time_Diff"
  next
}
$NF!="Failed"{
  $(NF+1)=$(NF-1)-$NF
}
1
'  Input_file | column -t

Output will be as follows.

Done  City        Start_time  End_time  Time_Diff
Yes   Chicago     18          10        8
Yes   Atlanta     208         11        197
No    Minnetonka  57          Failed
Yes   Hopkins     112         80        32
No    Marietta    2018        Failed

Explanation: Adding complete explanation for above code now.

awk '                      ##Starting awk program from here.
FNR==1{                    ##Checking conditoin if line is very first line then do following.
  print $0,"Time_Diff"     ##Printing current line with string Time_Diff here on very first line to print headings.
  next                     ##next is awk keyword which will skip all further statements from here.
}
$NF!="Failed"{             ##Checking if last field $NF where NF is number of fields and $ means in awk field value is NOT failed then do following.
  $(NF+1)=$(NF-1)-$NF      ##Add a new column by doing $(NF+1) whose value will be difference of 2nd last column and last column as per samples.
}                          ##Closing this condition block here.
1                          ##Mentioning 1 will print edited/non-edited line for Input_file.
' Input_file   |           ##Mentioning Input_file name and passing awk program output to next command by using pipe(|).
column -t                  ##Using column -t will print the output in TAB separated format.

If you are considering Perl,

> cat kwa.in 
Done  City                               Start_time  End_time
  Yes   Chicago                            18          10
  Yes   Atlanta                            208         11
   No   Minnetonka                          57        Failed
  Yes   Hopkins                           112         80
   No   Marietta                          2018        Failed
> perl -lane ' print join(" ",@F,"Time_Diff") if $.==1; if($.>1 ) { $F[4]=$F[2]-$F[3] if not $F[3]=~/Failed/; print join(" ",@F) } ' kwa.in | column -t
Done  City        Start_time  End_time  Time_Diff
Yes   Chicago     18          10        8
Yes   Atlanta     208         11        197
No    Minnetonka  57          Failed
Yes   Hopkins     112         80        32
No    Marietta    2018        Failed
> 
Related