使用 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 来处理日志文件。
热门推荐
预科班的报名方式和流程详解
牙疼的应急处理
提升家庭能源效率:储能用逆变器的优势和选择要点
电力现货价格年度简版报告(2024年):走低的现货均价与新能源收入
sqlplus命令找不到怎么解决
“胸痛”的种类那么多,哪种最要命?
法定继承如何办理
继承土地和房产怎么办理
消防员的岗位职责与技能
多人联机解谜游戏推荐2025 可以和朋友一起玩的解谜游戏推荐
Excel表格中计算单价和总价的三种方法
美拉德过气了!今年秋冬最火的还得是实穿又时髦的巴恩风!
诸葛瞻为什么不固守待援,季汉灭亡的罪魁祸首到底是谁?
【电子通识】能用5V电源去驱动线圈电压12V的继电器吗?
深入解析贫困线对社会经济发展的影响与意义
倾听与鼓励:伴侣情感关系的基石
防晒霜不假白不油腻选哪种好
孩子长大能赚多少钱,看父母就知道
武汉:扩大内需战略背景下,从“中部支点”迈向“全国支点”的深度解析
高光哑光眼影的区别
基于IPsec VPN的校园网络安全解决方案
英国教师薪资全解析:基础工资、地区差异与职业发展路径
如何规划并预约海南出岛旅游?全面指南助您顺利出行
王殿武:面对比自己强大的对手极其有效的思维策略
左旋肉碱能提升耐力吗
我国四大直辖市GDP全部公布,北京增量2489.4亿重庆增量1578.87亿
全球6G技术大会在宁开幕!凝聚全球共识,让6G“叫好又叫座”
获取考研调剂信息的三种渠道
期货低吸高抛的策略是什么?如何有效执行这一策略?
如何掌握高抛低吸的技巧并实现盈利目标?