如何在Bash中对日志按操作分组并统计子操作数量
解决Bash日志中按操作分组统计子操作数量的问题
没问题,我来帮你搞定这个需求!你需要从日志里提取每个Job(也就是你说的operation)对应的Tasks(sub-operation)数量,不管是按每行输出单次汇报的数量,还是按Job分组求和总数量,用awk都能轻松实现,比你之前尝试的命令精准得多。
核心思路拆解
你的日志每行结构很清晰:
- 操作名(Job)在
Job:之后、;之前,格式是ingestion-xxx - 子操作列表(Tasks)在
Tasks: [之后、]之前,用,分隔
我们需要先提取这两部分内容,再统计每个Job对应的子操作数量。
方案1:输出每行日志的单次汇报统计
如果你需要保留每条日志的独立统计(像你给出的示例结果那样,允许同一个Job多次出现),可以用这个命令:
awk ' BEGIN { print "operationName suboperationCount" } match($0, /Job: ([^;]+)/, job) && match($0, /Tasks: \[([^\]]+)\]/, tasks) { # 提取操作名 job_name = job[1] # 分割子操作列表,统计数量 split(tasks[1], task_list, /, /) task_count = length(task_list) # 输出结果 print job_name, task_count } ' xlogs.txt > fileresult.txt
命令解释:
BEGIN块:先打印表头,完全符合你要的输出格式match()函数:用正则精准捕获Job和Tasks的内容(需要awk 4.0及以上版本,大部分现代Linux/macOS系统都满足)split():把逗号分隔的子操作字符串拆成数组,数组长度就是子操作的数量- 最后自动把结果写入指定的
fileresult.txt文件
如果你的系统是旧版awk(不支持match()的第三个捕获参数),可以用这个兼容版本:
awk ' BEGIN { print "operationName suboperationCount" } /Job: / && /Tasks: \[/ { # 提取操作名 job_start = index($0, "Job: ") + 5 job_end = index(substr($0, job_start), ";") - 1 job_name = substr($0, job_start, job_end) # 提取子操作列表 task_start = index($0, "Tasks: [") + 8 task_end = index(substr($0, task_start), "]") - 1 task_str = substr($0, task_start, task_end) # 统计子操作数量 task_count = split(task_str, task_list, /, /) print job_name, task_count } ' xlogs.txt > fileresult.txt
方案2:按操作分组求和总数量
如果你需要统计每个Job的总子操作数(合并同一Job的所有汇报记录),可以修改成用关联数组累加:
awk ' match($0, /Job: ([^;]+)/, job) && match($0, /Tasks: \[([^\]]+)\]/, tasks) { job_name = job[1] task_count = split(tasks[1], task_list, /, /) total[job_name] += task_count } END { print "operationName suboperationCount" for (job in total) { print job, total[job] } } ' xlogs.txt > fileresult.txt
为什么你之前的命令不行?
你尝试的cat xlogs.txt | grep 'ingestion' | uniq | wc -w逻辑太粗糙:
grep 'ingestion'只是筛选包含关键字的行,没有精准定位Job或Tasksuniq直接去重会丢失大部分有效汇报记录wc -w只是统计所有单词的总数,完全没有提取Job和统计子操作的逻辑,自然得不到你要的分组统计结果
内容的提问来源于stack exchange,提问作者Xbreizh
相关产品推荐
相关产品推荐

