文本处理核心工具:grep、cut、sort、uniq、tr 的常用技巧

日志解析说白了就是跟文本打交道。HSM 日志动辄几万行,你要是不懂这几个小工具,光靠眼睛看,眼睛会瞎的。

我个人习惯把这四个工具当作管道里的积木——grep 负责筛选,cut 负责切字段,sort 和 uniq 负责排序去重,tr 负责清洗。它们单独用很弱,但组合起来威力巨大。我先一个个讲清楚,最后给你看一个真实案例。

grep:筛选你真正关心的行

grep 是日志分析里出场率最高的工具。它的核心逻辑就一句话:保留匹配模式的行。

常用选项速查

选项作用典型场景
-i忽略大小写日志里 ERROR 和 error 混用
-v反向匹配,排除指定行去掉注释行或调试信息
-E扩展正则,支持 | 等同时匹配多个关键词
-c只统计行数,不输出内容快速了解某类事件出现多少次
-A / -B / -C打印匹配行前后若干行看异常发生时的上下文

我记得刚接手一个 HSM 项目时,日志里报错总是夹杂在大量成功记录里。用 grep -i -E "fail|error|timeout" 一下就抓住了所有异常,省了我半天时间。

小技巧:如果你不确定日志里有没有某个关键词,先用 grep -c 看看数量。如果结果是 0,就不用再花时间翻屏了。
避坑:我曾经吃过一次哑巴亏——日志文件里的 tab 和空格混排,grep 按空格写的模式死活匹配不上。后来用 grep $'\t' 才搞定。记住:永远确认你查找的模式跟实际字符一致。

cut:像手术刀一样切字段

grep 筛出行,cut 则从行里提取你想要的列。日志通常是固定分隔符格式(比如冒号、逗号、空格),用 cut 最方便。

常用用法:

  • -d 指定分隔符,默认是 tab
  • -f 指定要取的字段编号,从 1 开始
# 假设日志格式:2025-01-15 14:30:00,INFO,User login success
cut -d',' -f2 log.txt          # 提取第二个字段:INFO
cut -d',' -f1,3 log.txt       # 提取第一和第三字段

但有个坑:如果某行分隔符数量不一致,cut 会只输出到实际存在的字段为止,不会报错。我建议先用 awk 处理更复杂的场景,单纯取固定列时 cut 足够。

sort + uniq:排序和去重的黄金组合

日志里经常要统计某类事件有多少种、出现频次。这俩工具通常连着用:先 sort 把相同内容排在一起,再 uniq 去重并计数。

sort 常用选项

选项作用示例
-n按数值排序按时间戳排序
-r降序排在最前面的是最大值
-k指定排序字段按第二列排序
-t指定字段分隔符与 cut 类似

uniq 常用选项

选项作用
-c显示每行重复次数
-d只显示重复行
-u只显示唯一行

实战中我经常这样用:

# 统计各种日志级别出现的次数
grep -oP '\b(INFO|WARN|ERROR|DEBUG)\b' log.txt | sort | uniq -c | sort -rn

这个管道先提取所有日志级别关键词,排序后去重计数,最后按次数降序排列。最高频的日志类别一目了然。

关键点:uniq 只对相邻的重复行有效。所以 用 uniq 之前必须先 sort,否则结果会出错。这是我见过最多的低级错误。

tr:字符串清洗工

tr 能做小范围的字符转换、删除、压缩。日志里常见的场景:去掉文件中的 ^M 回车符、统一大小写、替换分隔符。

# 将日志中所有大写字母转小写
tr 'A-Z' 'a-z' < log.txt

# 删除所有数字
tr -d '0-9' < log.txt

# 压缩连续的空格为单个空格
tr -s ' ' < log.txt

注意:tr 只处理字符,不处理字符串。你想把 "ERROR" 替换成 "ER" 用 tr 不行,得用 sed。tr 适合做粗粒度清洗,比如把制表符换成逗号,方便后续用 cut 处理。

我记得有一次客户发来的日志里混着全角空格(Unicode 0xa0),导致字段切分总出错。用 tr '\240' ' ' 先把全角空格替换成普通空格,后面就顺畅了。这种小坑你不实际操作很难碰到。

组合实战:一分钟统计 HSM 错误分类

下面我用一个真实需求串起所有工具。假设日志格式如下:

2025-01-15 14:30:00 [WARN] HSM: slot 0 key operation timeout
2025-01-15 14:31:12 [ERROR] HSM: PIN verification failed
2025-01-15 14:32:05 [INFO] HSM: session established
2025-01-15 14:33:44 [ERROR] HSM: key not found in device
2025-01-15 14:34:01 [WARN] HSM: certificate expired

我想知道:每个错误类型出现了几次?

grep -oP '\[(WARN|ERROR)\].*' log.txt |  # 只保留包含 WARN 或 ERROR 的行(其实 grep 可以换,这里演示 grep 筛选)
cut -d']' -f2 |                          # 取 ] 后面的内容
sed 's/^ *//' |                          # 去掉开头空格(sed 后续章节会讲,但这里备用)
sort | uniq -c | sort -rn                # 统计频次,降序排列

输出:

   1 key operation timeout
   1 PIN verification failed
   1 key not found in device
   1 certificate expired

如果日志有上万行,这个管道几秒就出结果,手动做根本不可能。

知识体系:这些工具在管道中的协作逻辑

下面这张图能帮你理解它们怎么配合:

文本处理工具在日志管道中的协作流程 原始日志 grep 筛选 cut 切字段 tr 清洗 sort + uniq 统计结果 💡 管道协作要点 • 顺序至关重要:先用 grep 减少行量,再用 cut 缩减列宽 • tr 通常作为前置清洗,去掉杂乱字符后再用其他工具

你看,每个工具负责一个环节,通过管道串起来后就能完成复杂的日志解析任务。记牢这个流程,以后遇到文本处理需求,先想想能用哪几个工具组合,而不是一上来就写 Python 脚本。

我个人的经验法则:能用管道解决的就不要写脚本。Shell 管道一次执行,性能远好于循环读文件。而且管道代码容易复用,把前面的命令换成另一个文件就行。