如何用grep反向搜索文件?提取日志特定关键词最后一行方案咨询
问题描述
需要从多个日志文件中提取每个文件内包含UNKNOWN_TOPIC_OR_PARTITION的最后一行内容,日志文件为自上而下写入,最新内容在文件底部;需处理名称各异的文件,排除后缀为.1/.2/.3/.4/.5的文件。当前使用命令missingTopics=$(grep -Ri -m1 --exclude=*.{1,2,3,4,5} UNKNOWN_TOPIC_OR_PARTITION /app/tibco/log/tra/domain/)无法满足需求,询问grep是否为最佳方案,或有无更适配的方法。
解决方案
grep并非最优选择,因为默认从上到下读取文件,-m1参数只会返回每个文件中第一个匹配的行,而你需要的是文件底部的最后一个匹配行。以下是两种更适配的方案:
方案1:结合tac与grep
tac会倒序读取文件(从最后一行到第一行),此时用grep -m1就能拿到原文件的最后一个匹配行。通过find遍历目标目录下符合条件的文件:
find /app/tibco/log/tra/domain/ -type f ! -name "*.{1,2,3,4,5}" -exec sh -c 'tac "$1" | grep -m1 "UNKNOWN_TOPIC_OR_PARTITION"' _ {} \;
如果需要同时输出文件名,可修改为:
find /app/tibco/log/tra/domain/ -type f ! -name "*.{1,2,3,4,5}" -exec sh -c 'match=$(tac "$1" | grep -m1 "UNKNOWN_TOPIC_OR_PARTITION"); if [ -n "$match" ]; then echo "$1: $match"; fi' _ {} \;
方案2:使用awk处理
awk可以逐行遍历文件,记录最后一个匹配的行,在文件遍历结束后输出结果,无需倒序读取:
find /app/tibco/log/tra/domain/ -type f ! -name "*.{1,2,3,4,5}" -exec awk '/UNKNOWN_TOPIC_OR_PARTITION/{line=$0} END{if(line != "") print FILENAME ": " line}' {} \;
这个命令会自动输出文件名和对应的最后匹配行,没有匹配的文件则不会输出。
原命令失效原因
你当前使用的grep -Ri -m1逻辑存在两个问题:
-m1在递归模式下,会在找到第一个匹配的文件中的第一行匹配内容后就停止遍历,不会处理所有文件;- 即使去掉递归限制,grep从上到下读取文件,
-m1返回的是每个文件中最早出现的匹配行,而非你需要的最新(底部)的匹配行。
内容的提问来源于stack exchange,提问作者Niels Beukenkamp
相关产品推荐
相关产品推荐

