从 Bash 中的日志文件中提取事件之间的时间

从 Bash 中的日志文件中提取事件之间的时间

我有一个文件/tmp/log/1GPS_garmin2.log,我想计算车辆第一次停车和最后一次停车之间经过了多少时间。

以下是数据示例:

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

$GPVTG行包含两个星号之间的车辆速度(文件中没有星号)。该$GPGGA行包含时间,时间也位于两个星号之间。前两个字符是小时,接下来的两个字符是分钟,最后两个字符是秒。

当速度为 0000 时,车辆停止。我需要第一次和最后一次停止的时间,以便我可以将其更改为秒并写入log.txt

我可以进行更改和书写,但需要帮助来查找车辆首末站的时间。

这是我的 run.sh 文件:

#!/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

我已经计算了平均速度和停车次数。

awk注意:我是 bash 的新手,所以我的解决方案不是最适合这项任务的,但是在我学会其他 bash 实用程序之前我不想使用它。

答案1

从您的样本来看:

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

笔记

  • -n在我们要求之前不要打印任何内容
  • -r使用 ERE
  • /0000/N;N找到一行0000并阅读接下来的两行
  • s/old/newold用。。。来代替new
  • .*行中的任何字符
  • ([^,]+)保存一些不在,这个位置的字符
  • \1反向引用已保存的模式
  • |将输出传递给另一个sed(不优雅的)
  • '1p;$p'打印第一行并打印最后一行

至于换算成秒数,就交给你了……

答案2

我会用awk它来做类似的事情。

这个想法是将记录(行)拆分为逗号分隔的字段,然后:

  • 如果第一个字段以 结尾$GPVTG,第八个字段以 开头0000,则设置一个布尔标志来指示车辆已停止
  • 当第一个字段结束$GPGGA且车辆停止时,保存第二个字段的距离值
  • 最后,打印第一个和最后一个距离值

所以

#!/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]);
}

相关内容