首页 > 解决方案 > 从多个日志文件中提取给定开始时间和结束时间之间的记录

问题描述

我们有日志文件,其格式将包含数百万条记录:

xyz,xyz, YYYY-MM-DD HH:MM:SS ,....,

我们将得到格式为:YYYYMMDDHHMMSS的开始时间和结束时间作为 shellscript 的输入。我们想从时间戳在开始时间和结束时间之间的所有日志文件中提取记录。

日志中的单条记录:abc,def,ghi, 2018-06-03 11:00:00 ,...,xyz

包装脚本:xyz.sh '20180603112000' '20180604120000'

预期输出:给定两个时间戳之间的所有记录。

标签: bashshellawksedgrep

解决方案


#!/bin/sh

d4="([0-9]{4})"
d2="([0-9]{2})"
pattern="$d4$d2$d2$d2$d2$d2"
replace='\1-\2-\3 \4:\5:\6'
from=$(echo "$1" | sed -r "s/$pattern/$replace/")
to=$(echo "$2" | sed -r "s/$pattern/$replace/")

sed -n "/$from/,\$p;/$to/q" file

在简单的英语中,它包括 $from 的第一个匹配项和匹配 $to 的第一行。

具体来说,脚本首先将输入转换为文件中预期出现的时间戳。然后 sed 默认不打印 (-n) 迭代文件,但打印从第一行到最后一行 ($) 的所有内容,但是如果遇到 $to,sed 将退出。

虽然这个解决方案并不完美。它的工作假设是每一秒至少包含一个日志行。或者至少搜索的秒数。通常,您不需要按秒提取日志行,我建议按小时或分钟提取块。当然,除非你有大量的日志行,在这种情况下,我认为这个假设成立。其次,它假设日志行中的数据不包含任何时间戳。如果数据本身包含时间戳,则此功能可能会中断。

更新: 我不太喜欢我给出的解决方案,因为它只打印与 $to 匹配的第一行。它很容易制作,但可能不是你想要的。这是一个在匹配 $to 的第一行之前停止的解决方案:

sed -n "/$from/,\$p" file | sed "/$to/Q"

你可以通过一个 sed 调用来做到这一点,但它有点难以理解:

sed -n "/$from/,\${/$to/Q;p}" file

这是一个包含所有匹配 $to 的行的解决方案

sed -n "/$from/,\$p" file | sed "/$to/{/$to/{N};q}"

新部分的说明: Q 将在自动打印之前退出,但由于我使用 p 进行打印,我必须确保 Q 在 p 之前触发/$to/Q;p,或者使用单独的 sed 调用以获得更易于理解的解决方案。

第二种解决方案只是自动打印,直到遇到 $to /$to/。然后它将匹配 $to 的每个后续行附加到 patspace /$to/{N}。最后q打印 patspace 并退出 sed。


推荐阅读