Awk 在两个时间戳之间提取日志最有效的方法是什么?

Awk 在两个时间戳之间提取日志最有效的方法是什么?,awk,grep,text-processing,Awk,Grep,Text Processing,我有一个bash脚本,它从两个时间戳之间的文件中提取日志。但是,随着文件越来越大(超过2GB,高达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/

我有一个bash脚本,它从两个时间戳之间的文件中提取日志。但是,随着文件越来越大(超过2GB,高达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
我对awk、sed和grep不太熟悉,如有任何建议,将不胜感激。也许用另一种语言比如python会更好?
谢谢

在我看来,您应该重新格式化日志的输出方式,使其格式一致(即时间戳始终位于第一列),这样您的awk就可以工作了

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

试试这个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 ""
}
处理:


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

awk '$3=="03/09"{s=1} s; $3=="03/11"{exit}' log_file
将以09年3月的第一个实例开始,并以2011年3月的第一个实例退出。如果第二天可能不在文件中,您可以将其更改为
$3>“03/10”
,以使其对错过的日期更有效

提前退出可能会加快文件开头日期的处理速度,但在以后的日子里不会,因为它仍然需要扫描文件

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


请注意,摘录的最后一行将故意使用exit值,以便您可以检查假阳性匹配。

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

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

还有一些其他的想法来加速它。特别是使用fgrep而不是grep。

这两行
奋力河:03/09/2017 02:40:42:00400004 047B0012奋力河:71[SDIO87871]:
之间有一个换行符,但您希望它们被视为一行。为什么?最有效的方法是从一个好的时间戳格式开始,该格式可以在不解析其元素的情况下进行比较。@Eric,是否有两行以上的行可以作为一行处理?@RomanPerekhrest这是保存日志的方式。我控制不了。我不认为如果我的awk命令在一行中会有什么不同?@Erik,如果它是一行,那么解析起来就容易多了。在其他情况下,格式是不清楚的,没有预料到谢谢你,但它是一个设备,输出这些日志。它们会自动保存在服务器中,因此我无法重新格式化。啊,好的,明白了。让我发布另一个想法,一些行使用
$2
作为年份。您可以通过将
s
放在末尾来保存分号。考虑<代码> AWK“$ 3==“03 / 11”=2美元=“03 / 11/2017”{退出} $==“03 / 09”=$2==“03/09/09”{S==} s LogyFrase< /Cord> >我认为这些行是前行的延续。我不这样认为;请看问题的最后一段文字,我几乎可以肯定,但我们必须同意不同意,直到OP对这个话题发表评论。
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
awk '$3=="03/09"{s=1} s; $3=="03/11"{exit}' log_file
fgrep -a -A -m 1 1000000 "03/09" fileName.txt | fgrep -a -B 1000000 "03/10"