如何使用grep查找损坏的NMEA日志句子?

时间:2020-03-05 18:45:38  来源:igfitidea点击:

我的GPS记录器有时在日志文件的末尾留下"未完成"行。我认为它们只是在末尾,但我想检查所有行以防万一。

一个完整的例句示例如下:

$GPRMC,005727.000,A,3751.9418,S,14502.2569,E,0.00,339.17,210808,,,A*76

该行应以" $"符号开头,并以" *"和两个字符的十六进制校验和结尾。我不在乎校验和是否正确,只要它存在即可。它还需要忽略没有校验和且位于每个文件开头的" ADVER"语句。

以下Python代码可能有效:

import re
from path import path
nmea = re.compile("^$.+\*[0-9A-F]{2}$")
for log in path("gpslogs").files("*.log"):
   for line in log.lines():
      if not nmea.match(line) and not "ADVER" in line:
         print "%s\n\t%s\n" % (log, line)

有没有办法用grep或者awk或者简单的方法做到这一点?我还没有真正想出如何让grep来做我想做的事情。

更新:感谢@Motti和@Paul,我能够获得以下内容来完成几乎我想做的事情,但是必须使用单引号并删除尾部的$才起作用:

grep -nvE '^$.*\*[0-9A-F]{2}' *.log | grep -v ADVER | grep -v ADPMB

出现另外两个问题,如何使它忽略空白行?我可以合并后两个greps吗?

解决方案

回答

最少的测试表明应该这样做:

grep -Ev "^$.*\*[0-9A-Fa-f]{2}$" a.txt | grep -v ADVER
  • -E使用扩展的正则表达式
  • -v显示不匹配的行
  • ^开头为
  • 。* 任何事物
  • \ *星号
  • [0-9A-Fa-f]十六进制数字
  • {2}恰好是前两个
  • $行尾
  • | grep -v ADVER清除ADVER行

HTH,Motti。

回答

@Motti的答案不会忽略ADVER行,但是我们可以轻松地将该grep的结果传递给另一个:

grep -Ev "^$.*\*[0-9A-Fa-f]{2}$" a.txt |grep -v ADVER

回答

@Tom (rephrased) I had to remove the trailing $ for it to work

删除$表示该行可能以其他结尾(例如,将接受以下内容)

$GPRMC,005727.000,A,3751.9418,S,14502.2569,E,0.00,339.17,210808,,,A*76xxx
@Tom And can I combine the last two greps?
grep -Ev "ADVER|ADPMB"

回答

@Motti:组合grep不起作用,没有效果。

我知道没有尾随的$校验和仍然可以匹配其他东西,但是它根本不起作用,所以我别无选择。

GNU grep 2.5.3和GNU bash 3.2.39(1)是否有任何区别。

而且看起来日志文件正在使用DOS换行符(CR + LF)。 grep是否需要一个开关来正确处理?

回答

汤姆

GNU grep 2.5.3 and GNU bash 3.2.39(1) if that makes any difference.
  And it looks like the log files are using DOS line-breaks (CR+LF). Does grep need a switch to handle that properly?

我在Windows上使用grep(GNU grep)2.4.2(真可惜!),它对我有用(并且DOS换行符自然被接受),目前我真的没有访问其他操作系统的权限。所以很抱歉,但我将无法为我们提供进一步的帮助:o(