日志正则匹配失败应先检查编码与换行符,用file -i和cat -A诊断,再用dos2unix或sed去BOM;提取错误需大小写不敏感、含上下文、匹配时间戳并排除干扰;结构化提取优先用awk而非cut。

grep + 正则匹配失败时,先检查日志编码和换行符
很多日志提取失败不是正则写错,而是文件本身含 ^M(DOS 换行)、UTF-8 BOM 或混合编码。用 file -i logfile.log 查编码,用 cat -A logfile.log | head -n 3 看不可见字符。若发现 ^M,先用 dos2unix logfile.log 清理;若有 BOM,用 sed '1s/^\xEF\xBB\xBF//' logfile.log > clean.log 去除。
提取带时间戳的错误行,别只靠 grep "ERROR"
单纯 grep "ERROR" 会漏掉 error、Error、"err_code":500 这类变体,也抓不到上下文。实际应组合使用:
- 大小写不敏感 + 行号 + 向下两行:
grep -i -A 2 "error\|exception\|fail" app.log - 匹配 ISO 时间戳 + ERROR:
grep -E "^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}.*ERROR" app.log - 排除干扰词(如调试日志):
grep -i "error" app.log | grep -v -i "debug\|info\|success"
用 awk 提取结构化字段比 cut 更稳
日志字段分隔符不统一时(比如空格、制表符、多个空格混用),cut -d' ' -f5 极易错位。而 awk 默认以任意空白为分隔符,且支持条件过滤:
- 取第 4 列(响应码)且值为 5xx 的行:
awk '$4 ~ /^5[0-9]{2}$/ {print $0}' access.log - 按 JSON 字段提取(需日志是单行 JSON):
awk -F'"' '/"status":5/ {for(i=1;i - 跳过注释和空行再处理:
awk 'NF && !/^#/ {print $1, $4, $7}' audit.log
实时监控日志并高亮关键词,tail -f 配合 grep --color 不够用
tail -f app.log | grep --color=always -i "error" 在管道中会丢失颜色,且无法滚动查看上下文。更可靠的做法是:
- 用
multitail(需安装):multitail -e "ERROR|WARN" app.log,支持多文件、高亮、过滤、滚动回溯 - 用
grep缓存最近 100 行再过滤:tail -n 100 app.log | grep -i "timeout" && tail -f app.log | grep -i "timeout" - 避免终端卡死:加
--line-buffered强制逐行输出:tail -f app.log | grep --line-buffered -i "panic"
真正难的是日志格式不一致——比如同一服务在不同版本里把 trace_id 放第 6 列或第 12 列,这时候硬写列数不如先用 head -20 app.log | cat -n 看样本,再决定用正则还是 awk 的字段模式匹配。

















