Regex 如何过滤多行/分隔行中定义的模式

Regex 如何过滤多行/分隔行中定义的模式,regex,bash,shell,sed,Regex,Bash,Shell,Sed,以下是我的日志的简单通用规范: 一个请求出现,日志…[XXXHandler]提交时间… 获取锁并启动事务,日志…[XXXHandler][UID]开始时间… 业务完成并返回锁,日志..[XXXHandler][UID]花费时间… 实际上,有大量的请求与各自的UID一起涌入,三行模式相互混杂。这是其中的一部分: ~ cat sample.log [240] [DeleteAllLettersHandler] coming time [Fri Mar 18 05:00:00 GMT-06:00

以下是我的日志的简单通用规范:

  • 一个请求出现,日志
    …[XXXHandler]提交时间…
  • 获取锁并启动事务,日志
    …[XXXHandler][
    UID
    ]开始时间…
  • 业务完成并返回锁,日志
    ..[XXXHandler][
    UID
    ]花费时间…
实际上,有大量的请求与各自的UID一起涌入,三行模式相互混杂。这是其中的一部分:

~ cat sample.log
[240] [DeleteAllLettersHandler] coming time [Fri Mar 18 05:00:00 GMT-06:00 2016]
[240] [StartBiddingAllianceBossAuctionHandler] coming time [Fri Mar 18 05:00:00 GMT-06:00 2016]
[240] [DeleteAllLettersHandler] [13497] start time [Fri Mar 18 05:00:00 GMT-06:00 2016]
[240] [DeleteAllLettersHandler] [13497] spend time [1] dbs 1 dbu 1 | {}
[240] [StartBiddingAllianceBossAuctionHandler] [1495] start time [Fri Mar 18 05:00:00 GMT-06:00 2016]
[240] [GetMazeMainInfoHandler] coming time [Fri Mar 18 05:00:00 GMT-06:00 2016]
[240] [StartBiddingAllianceBossAuctionHandler] [1495] spend time [1] dbs 1 dbu 0 | {}
[240] [GetMazeMainInfoHandler] [8941] start time [Fri Mar 18 05:00:00 GMT-06:00 2016]
[240] [GetResHarvestInfoHandler] coming time [Fri Mar 18 05:00:00 GMT-06:00 2016]
[240] [GetResHarvestInfoHandler] [1807] start time [Fri Mar 18 05:00:00 GMT-06:00 2016]
[240] [RCHandler] coming time [Fri Mar 18 05:00:00 GMT-06:00 2016]     ## gotcha
[240] [GetMazeMainInfoHandler] [8941] spend time [10] dbs 27 dbu 2 | {}
[240] [GetResHarvestInfoHandler] [1807] spend time [5] dbs 15 dbu 4 | {}
[240] [StartBiddingAllianceBossAuctionHandler] coming time [Fri Mar 18 05:00:00 GMT-06:00 2016]
[240] [StartBiddingAllianceBossAuctionHandler] [18052] start time [Fri Mar 18 05:00:00 GMT-06:00 2016]
[240] [StartBiddingAllianceBossAuctionHandler] [18052] spend time [1] dbs 1 dbu 0 | {}
[240] [GetResourceAmount] coming time [Fri Mar 18 05:00:00 GMT-06:00 2016]
[240] [GetResourceAmount] [29063] start time [Fri Mar 18 05:00:00 GMT-06:00 2016]
[240] [GetResourceAmount] [29063] spend time [1] dbs 3 dbu 0 | {}
我的要求是过滤日志,删除杂乱的三行模式,同时我可以看到哪个处理程序挂起(日志即将出现,但没有开始时间)


以下是我的解决方案:

- cat process.sh

sed -r '
    $!N
    $!N
    $!N
    s/(([^\n]*\n)*)[^\n]*\[([^\n]*)\] coming time[^\n]*\n(([^\n]*\n)*)[^\n]*\[\3\] \[([^\n]*)\] start time[^\n]*\n(([^\n]*\n)*)[^\n]*\[\3\] \[\6\] spend time[^\n]*(.*)/\1\4\7\9/
    t print     
    P
    D

    :print
' |

grep -v '^ *$'
这可以过滤一些模式,但不能过滤所有模式,因为sed可以处理分散在三行或四行中的一个模式(sed轮加可能更多)

~./process.sh
使用过滤后的日志作为种子,反复过滤,我可以得到我想要的结果:

~ ./process.sh < sample.log | ./process.sh
[240] [GetMazeMainInfoHandler] coming time [Fri Mar 18 05:00:00 GMT-06:00 2016]
[240] [GetMazeMainInfoHandler] [8941] start time [Fri Mar 18 05:00:00 GMT-06:00 2016]
[240] [RCHandler] coming time [Fri Mar 18 05:00:00 GMT-06:00 2016]     ## gotcha
[240] [GetMazeMainInfoHandler] [8941] spend time [10] dbs 27 dbu 2 | {}

~ ./process.sh < sample.log | ./process.sh | ./process.sh
[240] [RCHandler] coming time [Fri Mar 18 05:00:00 GMT-06:00 2016]     ## gotcha
~./process.sh
似乎我只需要再过滤几次就可以得到最终需要的结果。所以我问了一个问题:, @三重答案对我来说很有用。大约经过五次过滤后,我可以得到每个日志的最终结果


但耗时太多,一个10K行日志通常需要10分钟才能通过这种方式进行过滤

所以我的问题是,你能想出更好的方法吗?或者如何改进我的方式,让它运行得更快


谢谢你抽出时间

我认为bash不能胜任你的问题


我想推荐您尝试perl。解析日志并将[Handler Name,question,start,finish]四倍保存到一个哈希表中,然后您可以扫描哈希表以查找哪个处理程序挂起。这是一个更具扩展性的解决方案,IMHO。

我认为bash不能胜任您的问题


我想推荐您尝试perl。解析日志并将[Handler Name,question,start,finish]四倍保存到一个哈希表中,然后您可以扫描哈希表以查找哪个处理程序挂起。这是一个更具扩展性的解决方案,IMHO。

对您来说,计算未来时间和开始时间记录是不够的?@user3132194我必须找到挂起的处理程序。如果挂起的处理程序再也不会启动,您可以通过获取每个处理程序的最后一次出现次数来简化任务,并检查它是否包含
coming time
@Hedley Yan我的意思是您可以按处理程序计算coming和start记录的出现次数。如果它们在很长一段时间内不同,那么这个处理程序就出了问题。如果它是某种监视任务,那么您可以通过将
tail-f
管道连接到脚本来在线检查它,这应该可以缓解性能问题。@user3132194明白您的意思,Thx对您来说,计算未来时间和开始时间记录是不够的?@user3132194我必须找到挂起的处理程序。如果挂起的处理程序不再启动,您可以通过获取每个处理程序的最后一次出现次数来简化任务,并检查它是否包含
coming time
@Hedley Yan我的意思是您可以按处理程序计算coming和start记录的出现次数。如果它们在很长一段时间内不同,那么这个处理程序就出了问题。如果它是某种监视任务,那么您可以通过将
tail-f
管道连接到脚本来在线检查它,这应该可以缓解性能问题。@user3132194明白您的意思,谢谢您的建议!我不使用perl或其他高级语言有两个原因:1。在三行模式中还有其他日志信息混乱,这对我很有帮助,我必须保留它们。2.一个确定的[XXHandler][UID]。。。可能发生多次,并且处理程序和UID组合被分解。如果我使用散列来帮助我过滤模式,我也怀疑其效率。无论如何,我也想看看还有没有其他微妙的解决办法。@HedleyYan,你的任务越复杂,你就越应该合理地使用高级语言。谢谢你的建议!我不使用perl或其他高级语言有两个原因:1。在三行模式中还有其他日志信息混乱,这对我很有帮助,我必须保留它们。2.一个确定的[XXHandler][UID]。。。可能发生多次,并且处理程序和UID组合被分解。如果我使用散列来帮助我过滤模式,我也怀疑其效率。无论如何,我也想看看还有没有另一个微妙的解决办法。@HedleyYan,你的任务越复杂,你就越应该合理地使用advance
~ ./process.sh < sample.log | ./process.sh
[240] [GetMazeMainInfoHandler] coming time [Fri Mar 18 05:00:00 GMT-06:00 2016]
[240] [GetMazeMainInfoHandler] [8941] start time [Fri Mar 18 05:00:00 GMT-06:00 2016]
[240] [RCHandler] coming time [Fri Mar 18 05:00:00 GMT-06:00 2016]     ## gotcha
[240] [GetMazeMainInfoHandler] [8941] spend time [10] dbs 27 dbu 2 | {}

~ ./process.sh < sample.log | ./process.sh | ./process.sh
[240] [RCHandler] coming time [Fri Mar 18 05:00:00 GMT-06:00 2016]     ## gotcha