【linux】sed/awk命令检索区间日志

发布于:2025-09-11 ⋅ 阅读:(21) ⋅ 点赞:(0)

开发时如果需要检索一段时间内或者某个批量执行期间的所有日志,也就是区间日志时,手动检索会有一些问题:

  1. 如要查询一段时间前的日志(比如归档日志),需要一页一页翻,费时且费眼睛
  2. 使用grep筛选日志,但是只能搜索满足特定字段的日志,无法检索区间日志

为了实现区间日志的检索,可以使用sed/awk命令。这两个命令都无法直接处理压缩文件,需要先使用zcat读取压缩文件再通过管道传递。

1 grep+sed

sed是一个流编辑器,它一次读取一行文本,处理一行并输出一行,要检索日志区间时,主要使用

-- 1.行号匹配,输出从startrow行到endrow行的内容
sed -n 'startrow,endrowp' filename
-- 2.字符匹配,输出从匹配start的行到end的行的内容
sed -n '/start/,/end/p' filename

行号匹配注意:

  • startrow,endrow为起始行号,结束行号,p为打印命令(print)
  • sed默认处理一行之后会输出一行,因此需要使用-n+p来取消自动打印,只打印我们需要的行
  • 如果只有一个行号,则打印指定行
  • 打印到末尾,则区间为startrow,$

字符匹配注意:

sed匹配字符时,一旦匹配到start则会一直输出内容直到匹配到end,因此:

  • 如果文件包含多个顺序start...end,则会分批输出
  • 如果只有start,没有end,则会从start输出到文件末尾
  • 如果文件内容为start...start...end...end,那么会输出从第一个start第一个end区间里内容

匹配区间时候一般使用(真实使用这个最方便):

-- 1. 使用grep定位行号(如果是压缩文件,则使用zcat filename.tar.gz|grep -n "xxx")
grep -n "开始日志标志" filename
-- 2. 找到上述命令输出行号,比如 510:xxxxx,在该行号上面+大致区间长度即可,压缩文件同样使用zcat+管道
sed -n '510,550p' filename

2 awk

sed一般只用于简单的文本转换编辑,比如查找替换,但awk命令是一个更强大的文本处理器,可以处理更复杂的命令,比如计算、分析。

awk采用“模式-动作”对执行模型,命令基本结构是:

pattern {action}
pattern {action}
...

对于输入流/文件里的每一行,awk会依次检查每个pattern,如果匹配成功,则执行对应的action,如果某个action之后的pattern不需要继续匹配,则需在这个action加上next终止后续匹配如果action缺失,则采用默认动作{print $0},打印当前整行。

如果要打印开始日志结束日志中间的内容,使用如下命令,与sed一样,如果文件包含多组开始日志...结束日志,则会输出所有区间:

-- 模式使用'/xxx/'表明使用正则表达式模式
-- 1.1 不包括开始日志和结束日志行
awk '/开始日志/{flag=1;next} /结束日志/{flag=0} flag' filename 
-- 1.2 包括开始日志和结束日志行
awk '/开始日志/{flag=1} flag; /结束日志/{flag=0}' filename
-- 2. 语法糖,打印从开始日志行到结束日志行内的所有内容(包括首尾两行)
awk '/开始日志/,/结束日志/' filename

命令1.1的流程为:

  • 当匹配开始日志行时,将开关变量flag1,然后执行next跳过后续模式动作处理,直接读取下一行
  • 假设下一行是中间行,那么前两个正则匹配模式都失败,进行第三个flag模式,这是一个表达式模式,检查flag的值。当它非0或非空时为true,然后采用默认动作{print $0},打印当前整行,因此中间行能被打印
  • 当匹配结束日志行时,开关变量flag0,继续下一个模式,此时flag表达式判断为false,因此不打印

这个流程完成了从开始日志行到结束日志行之间内容的打印。1.2同样可以按照这个流程分析,它会打印包括开始日志行和结束日志行在内的所有区间内容。

命令2范围模式,格式为pattern1,pattern2 {action},是一种特殊模式,它表示从第一次匹配pattern1的行开始,到第一次匹配pattern2的行结束,之间的所有行都执行action动作。action缺失则打印整行。

3 sed/awk查找特定重复区间

当某功能或任务执行多次时,可能有多个任务开始...任务结束区间:

1:  任务开始
2...
10:  任务结束
11: xxxx
12: 任务开始
13...
22:  任务结束
...

3.1 查找第一个区间

sed/awk查找第一个区间日志都是在输出完后退出,sed使用qawk使用exit

sed -n '/任务开始/,/任务结束/p; /任务结束/q' filename
 
awk '/任务开始/{flag=1} flag; /任务结束/{print;exit}' filename
awk '/任务开始/,/任务结束/; /任务结束/{exit}' filename

3.2 查找第n区间

如果想要找到第n组日志可以用awk定义计数器(sed不支持复杂操作):

awk '/任务开始/{cnt++} cnt==2{print} /任务结束/ && cnt==2 {exit}' filename

3.3 最后一组/最新组

sed,awk都是流处理,无法回溯信息,因此无法得知当前区间是否是最后一次,所以最新一组日志需要使用反转命令第一次结束日志...开始日志区间再倒转即可。

tac filename | sed  -n '/任务结束/,/任务开始/p; /任务开始/q' filename
tac filename | awk '/任务结束/{flag=1} flag; /任务开始/{flag=0;exit}' | tac
tac filename | awk '/任务结束/,/任务开始/; 任务开始/{exit}' | tac


网站公告

今日签到

点亮在社区的每一天
去签到