user12064414
user12064414

Reputation: 13

Can someone explain this AWK command?

Im trying to calculate the average of a list of hours, I found an awk command that works pretty well but i want to know how is works.

This is my list of hours:

20:09
19:24
19:28

And this is the program

awk -F':' '
BEGIN {
    total=0;
}
{
    total+=(($1*3600)+($2*60)+$3);
} 
END {
    a=(total/NR); 
    printf "%02d:%02d:%02d\n",(a/3600),((a/60)%60),(a%60)
}' file

I understand the first part and how it convert everything into seconds but nothing more.

Upvotes: 0

Views: 71

Answers (2)

kvantour
kvantour

Reputation: 26581

Short answer: this code computes the average duration of some timing which is located in file file

I assume you have a file which looks something like:

00:02:30: something1
00:01:14: something2
01:02:04: something3

I also assume that the first three values represent a duration in hours minutes and seconds.

What the code does is per line extract the duration and convert it into total seconds and adds it to a value total. When all lines are processed, it computes the average duration by dividing it by NR which represents the total number of lines processed. It then prints the average value out by converting it back into hh:mm:ss

note: the code can be reduced into

awk -F':' '{t+=3600*$1 + $2*60 + $3}
           END{t/=NR; printf "%02d:%02d:%02d\n",t/3600,(t/60)%60),(t%60) }' file

Upvotes: 0

RavinderSingh13
RavinderSingh13

Reputation: 133770

Could you please try following explanation, based on OP's shown attempts.

# Start awk program from here, set field separator as :
awk -F':' '
# The BEGIN block is only executed once, when the script starts
BEGIN{
  # Initialize total
  total=0
}
# Main script executes for each input line
{
  # Convert to seconds: Multiply first field $1 by 3600 and second by 60
  # then add the terms together, and add to total
  total+=(($1*3600)+($2*60)+$3)
}
# The END block executes when we have finished reading all lines
END{
  # Calculate average: divide total by number of lines
  a=(total/NR)
  # Print result, where a/3600 is hours,
  # (a/60)%60 is remainder in minutes, a%60 remainder seconds
  # -- the %02d format specifier takes care to discard any decimals
  printf "%02d:%02d:%02d\n",(a/3600),((a/60)%60),(a%60)
}
' file   # input file name

Upvotes: 4

Related Questions