使用 awk 优雅地处理日志文件:从入门到实践
创作时间:
作者:
@小白创作中心
使用 awk 优雅地处理日志文件:从入门到实践
引用
1
来源
1.
https://jiejue.ai/2025/02/awk-log-processing-guide/
在日常工作中,我们经常需要处理各种格式的日志文件。有时候日志的格式并不理想,需要我们进行一些转换和处理才能更好地分析数据。本文将通过一个具体的应用场景,详细讲解如何使用awk这个强大的文本处理工具来优雅地处理日志文件。
问题场景
假设我们有一个应用程序生成的日志文件,每条记录包含了时间戳、事件类型、操作对象和相关进程信息。日志的原始格式如下:
2025-02-23 15:30:48.078 | Event: CREATE, Path: example.txt
相关进程:
AppOne(com.example.one)[最近活跃]
系统桌面(com.android.launcher)[最近活跃]
设置(com.android.settings)[最近活跃]
2025-02-23 15:31:01.218 | Event: MODIFY, Path: config.ini
相关进程:
AppTwo(com.example.two)[最近活跃]
系统桌面(com.android.launcher)[最近活跃]
...
这种格式虽然人眼容易读,但不利于我们用工具进行后续分析。我们希望:
- 过滤出特定文件的操作记录(比如只看 .txt 和 .ini 文件)
- 只保留第一个相关进程(通常是实际操作的进程)
- 将信息整理成表格形式,方便导入到其它工具处理
解决方案
让我们一步步来编写一个 awk 脚本来处理这个日志文件。
第一步:基本结构
首先,我们需要一个基本的脚本框架:
set raw_log my_app.log # 设置日志文件路径
awk '
BEGIN {
# 打印表头
printf("%-23s | %-12s | %-8s | %-20s | %s\n",
"TIMESTAMP", "EVENT", "PATH", "APP", "PACKAGE")
# 打印分隔线
printf("%.90s\n", "---")
}
# 后续处理逻辑会加在这里
' $raw_log
这个框架做了两件事:
- 定义了输出的表格结构
- 使用
printf格式化输出,确保各列对齐
第二步:匹配关键行
接下来,我们需要找到包含我们感兴趣文件的行:
/Path:.*(txt|ini)/ { # 匹配包含 txt 或 ini 的 Path 行
# 保存这一行,后面会处理
event_line = $0
# 读取下一行
getline
if ($0 ~ /相关进程:/) { # 检查是否是进程信息行
getline # 再读取一行得到第一个进程
process = $0
# 后续处理...
}
}
这段代码:
- 使用正则表达式匹配包含指定文件类型的行
- 用
getline读取后续行来获取进程信息 - 把需要的信息存储在变量中
第三步:提取信息
现在我们来提取需要的具体信息:
# 提取时间戳
timestamp = $1" "$2
# 提取事件类型
match($0, /Event: [^,]+/)
event_type = substr($0, RSTART+7, RLENGTH-7)
# 提取文件路径
match($0, /Path: [^ |]+/)
path = substr($0, RSTART+6, RLENGTH-6)
# 提取进程信息
match($0, /[^(]+\([^)]+\)/)
full_proc = substr($0, RSTART, RLENGTH)
split(full_proc, parts, "(")
app_name = parts[1]
package = substr(parts[2], 1, length(parts[2])-1)
这里使用了几个重要的 awk 函数:
match():在字符串中查找匹配的模式substr():提取子字符串split():分割字符串
第四步:格式化输出
最后,我们用格式化的方式输出提取的信息:
printf("%s | %-12s | %-8s | %-20s | %s\n",
timestamp, event_type, path, app_name, package)
格式说明:
%s:字符串占位符-12s:左对齐,宽度为12的字符串\n:换行符
完整脚本
把上面的部分组合起来,这就是我们完整的处理脚本:
set raw_log my_app.log
awk '
BEGIN {
printf("%-23s | %-12s | %-8s | %-20s | %s\n",
"TIMESTAMP", "EVENT", "PATH", "APP", "PACKAGE")
printf("%.90s\n", "---")
}
/Path:.*(txt|ini)/ {
# 提取时间戳
timestamp = $1" "$2
# 提取事件类型
match($0, /Event: [^,]+/)
event_type = substr($0, RSTART+7, RLENGTH-7)
# 提取路径
match($0, /Path: [^ |]+/)
path = substr($0, RSTART+6, RLENGTH-6)
# 读取进程信息
getline
if ($0 ~ /相关进程:/) {
getline
# 提取进程名和包名
match($0, /[^(]+\([^)]+\)/)
full_proc = substr($0, RSTART, RLENGTH)
# 分割进程名和包名
split(full_proc, parts, "(")
app_name = parts[1]
package = substr(parts[2], 1, length(parts[2])-1)
# 输出格式化的日志
printf("%s | %-12s | %-8s | %-20s | %s\n",
timestamp, event_type, path, app_name, package)
}
}' $raw_log
运行这个脚本后,我们会得到这样的输出:
TIMESTAMP | EVENT | PATH | APP | PACKAGE
---
2025-02-23 15:30:48.078 | CREATE | test.txt | AppOne | com.example.one
2025-02-23 15:31:01.218 | MODIFY | app.ini | AppTwo | com.example.two
实用技巧
测试正则表达式 :在编写复杂的正则表达式时,可以先用
echo和grep测试:echo "your test string" | grep "your regex"调试输出 :在开发过程中,可以使用
print语句来调试:print "Debug:", $0 # 打印当前行保存中间结果 :处理大文件时,可以先处理一小部分来测试:
head -n 100 big_log.txt | awk '你的脚本' > test_output.txt
小结
通过这个例子,我们学会了:
- 使用 awk 的基本语法和函数
- 如何处理多行日志记录
- 如何提取和格式化输出信息
这个脚本可以作为一个模板,通过修改正则表达式和输出格式,很容易适配其他类似的日志处理需求。希望这个教程能帮助你更好地理解和使用 awk 来处理日志文件。
热门推荐
国产电影的崛起与发展:近几年国产影片取得的辉煌成绩与未来趋势
提升患者体验 | 医院应如何运用候补挂号机制提高号源利用率?
黄金验真假设备的研究与应用
尾盘:美股跌幅扩大 道指下跌逾760点
U20国足备战沙特:541阵型成首选,重返世青赛仅差一步
《哪吒2》爆火!哪吒这一神话人物背后的故事,你知道吗?
政策发力与市场分化:2025年A股市场的投资逻辑与策略
中药,什么时间喝最好?
医聊 | 抬头看电脑,低头看手机,你的颈椎还好吗?
自媒体运营职业规划书怎么写(自媒体运营职业规划书怎么写好)
首进欧洲杯!除了K77,你对格鲁吉亚足球了解多少?
静电学在电子制造中的应用:IEC 61340-5-1标准的最佳实践指南
曲评杂谈|如何正确打开春晚相声
情人节怎么来的 中国三大传统情人节揭秘
年纪大了,经常压腿、拉筋,对身体是好还是坏?医生说出了实情
当洛天依、叶修直播带货,虚拟偶像与品牌还能玩多久?
去马来西亚留学好吗?谈谈我的亲身体验经历吧
Unity 3D游戏开发套件入门指南:基础功能详解
探索宇宙与量子的奥秘:书籍《宇宙从哪里来》解读
轮胎漏慢气必须要换胎?别浪费钱,其实自己动手就能修好
合成橡胶:成本驱动与需求变化博弈 市场价格维持震荡
撒贝宁浓重眉毛冲上热搜,为什么人的眉毛这么重要?
新型犯罪案件中无罪辩护的难点与应对
组织行为:探究高效协作的核心要素
烟台苹果打响“中国果业第一品牌”荣誉保卫战、产业攻坚战
红枣虽好,并非人人适宜!
《中庸》讲的是什么?——别误会,中庸可不是“平庸”!
烟气干燥技术详解:五大子系统助力高效干燥
这些非遗糕点,春节会化身吉祥信使代表美好寓意,你家餐桌上有吗?
如何在职业规划中发展你的人际关系和网络