【问题标题】:What is the most efficient way to extract logs between two time stamps?在两个时间戳之间提取日志的最有效方法是什么?
【发布时间】:2017-08-10 22:44:25
【问题描述】:

我有一个 bash 脚本,可以从两个时间戳之间的文件中提取日志。但是,随着文件变得越来越大(超过 2 GB,最高可达 10GB),完成所需的时间相当长(超过 20 分钟)

我的日志结构如下所示:

087B0037 08AD0056 03/09 02:40:40 [MMS:Main,INF] MMS state changed 
087B0037 096100BE 03/09 02:40:41 [Navigation,INF] CDDClient Initialize...
EndeavourDriver: 03/09/2017 02:40:42 :
00400004 047B0012 EndeavourDriver: 71 [SDIO87871]:

087B0037 0BE10002 03/10 06:40:40 [NNS:NNS,INF] Initializing NNS thread id 0x0BE10002...
087B0037 08AD0056 03/10 06:40:40 Initialized state: BITServer

我的脚本使用以下命令:

grep -a -A 1000000 "03/09" fileName.txt | grep -a -B 1000000 "03/10"

但是时间太长了。如果我添加时间(例如“03/09 02:”)会更快,但日志并不总是在运行,因此可能会丢失一些时间值。 日期值总是在第 3 列,所以我尝试使用 awk:

 awk '$3 >= "03/09" && $3 <= "03/10"' fileName.txt

但这并没有收集以下行:

EndeavourDriver: 03/09/2017 02:40:42 :
00400004 047B0012 EndeavourDriver: 71 [SDIO87871]:

我对 awk、sed 和 grep 不太熟悉,因此如有任何建议,我们将不胜感激。也许像python这样的不同语言的东西会更好? 谢谢

【问题讨论】:

  • EndeavourDriver: 03/09/2017 02:40:42 : 00400004 047B0012 EndeavourDriver: 71 [SDIO87871]: 行之间有一个换行符,但您希望它们被视为单行。为什么?
  • 最有效的方法是从一个不错的时间戳格式开始,无需解析其元素即可进行比较。
  • @Eric,是否应该将多于两行视为单行?
  • @RomanPerekhrest 这就是日志的保存方式。我无法控制那个。如果它在一行中,我认为它不会对我的 awk 命令产生影响?
  • @Erik,如果它是一个单一的,它会更容易解析。在其他情况下,格式不明确且出乎意料

标签: awk grep text-processing


【解决方案1】:

如果您的日志文件按时间顺序排列,并且您只想提取一两天,这可能对您有用

awk '$3=="03/09"{s=1} s; $3=="03/11"{exit}' log_file

将从 03/09 的第一个实例开始,并从 03/11 的第一个实例退出。如果文件中可能不存在第二天,也许您可​​以将其更改为 $3&gt;"03/10" 以使其对错过的日期更加稳健。

提前退出可能会加快文件开头日期的工作,但不是为了以后的日子,因为它仍然需要扫描文件。

此外,您的多行记录可能会出现意外匹配,因为您需要定义更好的记录结构或回退到代价高昂的正则表达式匹配。

请注意,提取的最后一行将有意包含退出值,以便您可以检查误报匹配。

【讨论】:

  • 有些行使用$2 表示年份。您可以通过将s 放在末尾来保存分号。考虑awk '$3 == "03/11" || $2 == "03/11/2017" { exit } $3 == "03/09" || $2 == "03/09/2017" { s = 1 } s' log_file
  • 我认为这些行是前几行的延续。
  • 我不这么认为;查看问题中的最后一段文字
  • 我几乎可以肯定,但我们必须同意不同意,直到 OP cmets 关于这个主题。
【解决方案2】:

IMO 我认为您应该重新格式化日志的输出方式,以便它们采用一致的格式(即时间戳始终在第一列中),然后您的 awk 就可以工作了。

否则,虽然有点笨拙,但您可以使用this 查找感兴趣的日期的第一个和最后一个匹配项,然后使用sed 选择该范围。

【讨论】:

  • 谢谢,不过是输出这些日志的设备。它们会自动保存在服务器中,因此我无法重新格式化。
  • 啊好的,知道了。让我发布另一个想法
【解决方案3】:

试试这个 awk 解决方案-

     cat time.awk
        {
        if($4 ~ /^[0-9][0-9]:[0-9][0-9]:[0-9][0-9]$/  && $3 >= "03/09" && $3 <= "03/10") 
            print $0
        else if($3 ~ /^[0-9][0-9]:[0-9][0-9]:[0-9][0-9]$/ && $2 >= "03/09/2017" && $2 <= "03/10/2017") 
        {
        x=$0
            print x;
        getline n
        print n
        }
        else

        print ""
}

输入文件:

cat f
087B0037 08AD0056 03/09 02:40:40 [MMS:Main,INF] MMS state changed 
087B0037 096100BE 03/09 02:40:41 [Navigation,INF] CDDClient Initialize...
EndeavourDriver: 03/09/2017 02:40:42 :
00400004 047B0012 EndeavourDriver: 71 [SDIO87871]:

087B0037 0BE10002 03/10 06:40:40 [NNS:NNS,INF] Initializing NNS thread id 0x0BE10002...
087B0037 08AD0056 03/10 06:40:40 Initialized state: BITServer
087B0037 08AD0056 04/10 06:40:40 Initialized state: BITServer

处理:

awk -f time.awk f
087B0037 08AD0056 03/09 02:40:40 [MMS:Main,INF] MMS state changed 
087B0037 096100BE 03/09 02:40:41 [Navigation,INF] CDDClient Initialize...
EndeavourDriver: 03/09/2017 02:40:42 :
00400004 047B0012 EndeavourDriver: 71 [SDIO87871]:

087B0037 0BE10002 03/10 06:40:40 [NNS:NNS,INF] Initializing NNS thread id 0x0BE10002...
087B0037 08AD0056 03/10 06:40:40 Initialized state: BITServer

【讨论】:

    【解决方案4】:

    您是否尝试过限制匹配次数?并使用 fgrep?这可能会显着缩短处理时间:

    fgrep -a -A -m 1 1000000 "03/09" fileName.txt | fgrep -a -B 1000000 "03/10"
    

    Here 是其他一些加快速度的想法。特别是使用 fgrep 而不是 grep。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-01
      • 2014-05-22
      • 2010-10-28
      • 2011-04-22
      • 1970-01-01
      相关资源
      最近更新 更多