0

I have a file /tmp/log/1GPS_garmin2.log and I want to calculate how much time passed between the first and last stop of a vehicle.

Here is a sample of the data:

181225.249849952:,06,,14,18,19,22,27,32,,,2.0,1.4,1.5*34
181225.254218266:$GPVTG,000.0,T,355.7,M,000.01,N,**0000**.02,K*79
181225.259072464:$GPRMC,161212.2,A,4653.89701,N,01940.55676,E,000.01,000.0,100913,004.3,E*59
181225.264592889:$GPGGA,**161212**.2,4653.89701,N,01940.55676,E,2,08,1.4,124.2,M,41.3,M,,*5C
181225.268283132:$GPGSA,A,3,,03,06,,14,18,19,22,27,32,,,2.0,1.4,1.5*34
181225.274272586:$GPVTG,000.0,T,355.7,M,000.01,N,0000.01,K*7A
181225.277401076:$GPRMC,161212.4,A,4653.89701,N,01940.55676,E,000.01,000.0,100913,004.3,E*5F
181225.280493945:$GPGGA,161212.4,4653.89701,N,01940.55676,E,2,08,1.4,124.2,M,41.3,M,,*5A
181225.283556186:$GPGSA,A,3,,03,06,,14,18,19,22,27,32,,,2.0,1.4,1.5*34
181225.286888004:$GPVTG,000.0,T,355.7,M,000.01,N,0000.01,K*7A
181225.290137581:$GPRMC,161212.6,A,4653.89701,N,01940.55677,E,000.01,000.0,100913,004.3,E*5C
181225.293265920:$GPGGA,161212.6,4653.89701,N,01940.55677,E,2,08,1.4,124.2,M,41.3,M,,*59
181225.297247457:$GPGSA,A,3,,03,06,,14,18,19,22,27,32,,,2.0,1.4,1.5*34
181225.300419979:$GPVTG,000.0,T,355.7,M,000.01,N,0000.02,K*79
181225.303577147:$GPRMC,161212.8,A,4653.89701,N,01940.55677,E,000.01,000.0,100913,004.3,E*52
181225.306632425:$GPGGA,161212.8,4653.89701,N,01940.55677,E,2,08,1.4,124.2,M,41.3,M,,*57
181225.310040084:$GPGSA,A,3,,03,06,,14,18,19,22,27,32,,,2.0,1.4,1.5*34
181225.313133946:$GPVTG,000.0,T,355.7,M,000.01,N,0000.01,K*7A
181225.317166965:$GPRMC,161213.0,A,4653.89701,N,01940.55677,E,000.01,000.0,100913,004.3,E*5B
181225.320426880:$GPGGA,161213.0,4653.89701,N,01940.55677,E,2,08,1.4,124.2,M,41.3,M,,*5E
181225.323792082:$GPGSA,A,3,,03,06,,14,18,19,22,27,32,,,2.0,1.4,1.5*34
181225.327003400:$GPVTG,000.0,T,355.7,M,000.01,N,0000.01,K*7A
181225.330192100:$GPRMC,161213.2,A,4653.89701,N,01940.55677,E,000.01,000.0,100913,004.3,E*59
181225.333141314:$GPGGA,161213.2,4653.89701,N,01940.55677,E,2,08,1.4,124.2,M,41.3,M,,*5C
181225.336206449:$GPGSA,A,3,,03,06,,14,18,19,22,27,32,,,2.0,1.4,1.5*34
181225.339610415:$GPVTG,000.0,T,355.7,M,000.01,N,0000.02,K*79
181225.342976480:$GPRMC,161213.4,A,4653.89701,N,01940.55678,E,000.01,000.0,100913,004.3,E*50
181225.346003737:$GPGGA,161213.4,4653.89701,N,01940.55678,E,2,08,1.4,124.2,M,41.3,M,,*55
181225.349040725:$GPGSA,A,3,,03,06,,14,18,19,22,27,32,,,2.0,1.4,1.5*34
181225.352282572:$GPVTG,000.0,T,355.7,M,000.01,N,0000.02,K*79
181225.355736225:$GPRMC,161213.6,A,4653.89700,N,01940.55678,E,000.01,000.0,100913,004.3,E*53
181225.359730217:$GPGGA,161213.6,4653.89700,N,01940.55678,E,2,08,1.4,124.2,M,41.3,M,,*56
181225.363299063:$GPGSA,A,3,,03,06,,14,18,19,22,27,32,,,2.0,1.4,1.5*34
181225.366588198:$GPVTG,000.0,T,355.7,M,000.01,N,0000.02,K*79
181225.371109954:$GPRMC,161213.8,A,4653.89700,N,01940.55678,E,000.01,000.0,100913,004.3,E*5D
181225.374346102:$GPGGA,161213.8,4653.89700,N,01940.55678,E,2,08,1.4,124.2,M,41.3,M,,*58
181225.377370616:$GPGSA,A,3,,03,06,,14,18,19,22,27,32,,,2.0,1.4,1.5*34
181225.380446435:$GPVTG,000.0,T,355.7,M,000.01,N,0000.02,K*79

The $GPVTG row contains the speed of the vehicle between two asterisks (the asterisks are not in the file). The $GPGGA row contains the time which is also between two asterisks. The first two chars are the hour, the next two are minutes and the last two are seconds.

The vehicle is stopped when speed is 0000. I need the time of the first and last stopping so that I can change it to seconds and write out to log.txt.

I can do the change and the writing out but need help to find the times of the first and last stops of the vehicle.

This is my run.sh file:

#!/bin/bash
fullfilename=$1
filename=$(basename "$fullfilename")
ext="${filename##*.}"

if [[ $# -ne 1 ]]; then
  echo "Error 1"
  exit 1
elif [[ $ext != "log" ]]; then
  echo "Error 2"
  exit 1
elif [[ ! -r $fullfilename ]]; then
  echo "Error 3"
  exit 1
else
  grep '$GPGGA' $1 > test1.txt
  grep '$GPVTG' $1 > test2.txt
  cut -c50-53 test2.txt > speed.txt
  cat speed.txt | wc -l > dealer.txt
  while read line
    do
      I=0; for N in $(cat speed.txt); do I=$(($I + 10#$N)); done;
      echo "average speed:" $(($I / $line)) >> log.txt
  done < dealer.txt
  grep '0000' speed.txt | wc -l > stop.txt
  while read stop
    do
      echo "number of stops:" $stop >> log.txt
  done < stop.txt
fi

I have already calculated the average speed and the number of stops.

Note: I'm a newbie in bash so my solution is not the best for this task, but I don't want to use awk yet until I've learned other bash utilities.

  • the speed (cut -c50-53 test2.txt) is always 0000? Are you asking for the cumulative time? Like, how much time passed between the first 0000 to the last 0000? How can we tell what that was? Do you basically want to add up all the fields after $GPGGA? – Zanna Apr 23 '17 at 10:19
  • Yes I cut 0000 because this is when the vechicle is stopped so I can calculate how many time was the vechicle stopped. Yes, basically I only need how many time passed between the first 0000 and last 0000. The problem is that the speed is in $GPVTG row and I need the time which is in $GPGGA row. So I need the commensurate time for the first and last stop (0000) then I can change the time to seconds and extract the first 0000 from the last 0000. – bozsi12 Apr 23 '17 at 10:31
3

From your sample:

$ sed -nr '/0000/N;N; s/.*GPGGA,([^,]+).*/\1/p' file | sed -n '1p;$p'
161212.2
161213.8

Notes

  • -n don't print anything until we ask for it
  • -r use ERE
  • /0000/N;N find a line with 0000 and read the next two lines
  • s/old/new replace old with new
  • .* any characters on the line
  • ([^,]+) save some characters that are not a , in this position
  • \1 backreference to the saved pattern
  • | passing the output to another sed (gracelessly)
  • '1p;$p' print line 1 and print the last line

And converting to seconds I leave to you...

  • I'm feeling to learn more about sed. :| Can you suggest any documnet/tutorial/etc? – Ravexina Apr 23 '17 at 11:16
  • @Ravexina I like this one – Zanna Apr 23 '17 at 11:20
2

I'd use awk for something like this.

The idea would be to split the records (lines) into comma-separated fields, and then:

  • if the first field ends in $GPVTG and the eighth field starts with 0000, then set a boolean flag to indicate that the vehicle is stopped
  • when the first field ends in $GPGGA and the vehicle is stopped, save the distance value from the second field
  • at the end, print the first and last distance values

So

#!/usr/bin/awk -f

function printsecs(s) { 
  print substr(s,5) + 60 * (substr(s,3,2) + 60 * substr(s,1,2));
}

BEGIN {FS=","}

$1 ~ /\$GPVTG$/ && $8 ~ /^0000/ {
  stopped = 1;
} 

$1 ~ /\$GPGGA$/ && stopped {
  t[++n] = $2; 
  stopped = 0; 
} 

END {
  printsecs(t[1]); printsecs(t[n]);
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.