You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

awk命令新手求助:日志异常单行化+按时间戳与关键词过滤

解决多行日志的awk过滤问题

作为awk新手,遇到多行日志(比如换行的异常堆栈)确实容易踩坑——毕竟默认awk是按行处理的,没法识别跨多行的单条日志。我来给你个实用的解决方案,核心思路是先把跨多行的日志合并成单行,再做过滤和搜索。

第一步:明确日志边界

首先得抓住你的日志特征:通常每条完整日志的开头都会有时间戳,而换行的异常信息行是没有的。比如你的日志时间戳是[YYYY-MM-DD HH:MM:SS]格式,那我们就用这个正则来识别每条日志的起始点。

第二步:编写awk处理脚本

下面这个脚本会帮你完成「多行日志合并+指定字符串搜索+时间范围过滤」三个需求:

BEGIN {
    # 替换成你要搜索的目标字符串,比如"ERROR"
    target_str = "你的搜索关键词"
    # 替换成你需要的时间范围,格式要和日志里的时间戳完全一致
    start_time = "2024-05-20 00:00:00"
    end_time = "2024-05-21 23:59:59"
}

# 匹配时间戳开头的行,作为单条日志的起始
/^\[([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2})\]/ {
    # 如果之前有累积的日志行,先检查是否符合过滤条件,符合就输出
    if (line != "") {
        if (index(line, target_str) != 0 && compare_time(log_time, start_time) >= 0 && compare_time(log_time, end_time) <= 0) {
            print line
        }
    }
    # 提取当前日志的时间戳(去掉前后的[])
    log_time = substr($0, 2, 19)
    # 初始化当前日志行
    line = $0
    next
}

# 非时间戳开头的行,追加到当前日志行(用|分隔原换行内容,方便区分)
{
    line = line " | " $0
}

# 处理最后一条日志,避免遗漏
END {
    if (line != "") {
        if (index(line, target_str) != 0 && compare_time(log_time, start_time) >= 0 && compare_time(log_time, end_time) <= 0) {
            print line
        }
    }
}

# 自定义时间比较函数:把时间转成秒数,方便判断是否在范围内
function compare_time(t1, t2) {
    split(t1, t1_parts, /[- :]/)
    split(t2, t2_parts, /[- :]/)
    # mktime函数把时间转成从1970年开始的秒数,忽略闰年日常使用足够
    t1_sec = mktime(t1_parts[1] " " t1_parts[2] " " t1_parts[3] " " t1_parts[4] " " t1_parts[5] " " t1_parts[6])
    t2_sec = mktime(t2_parts[1] " " t2_parts[2] " " t2_parts[3] " " t2_parts[4] " " t2_parts[5] " " t2_parts[6])
    return t1_sec - t2_sec
}

第三步:使用方法

  1. 把上面的脚本保存为process_log.awk文件
  2. 运行命令处理你的日志文件(比如app.log):
awk -f process_log.awk app.log

或者直接把脚本写在命令行里执行,省去保存文件的步骤。

关键调整点

  • 时间戳适配:如果你的日志时间戳格式不是[YYYY-MM-DD HH:MM:SS](比如是YYYY-MM-DDTHH:MM:SS),要修改匹配的正则表达式,以及substr的参数来正确提取时间戳。
  • 分隔符替换:脚本里用|连接换行的异常内容,你可以换成其他不冲突的符号(比如>>>)。
  • 兼容性提示:建议用GNU awk(gawk),它的mktime函数兼容性更好,大部分Linux系统默认就是gawk。

举个实际效果例子,假设你的日志里有这样的多行异常:

[2024-05-20 10:05:00] ERROR: Failed to process request
java.lang.NullPointerException
    at com.example.Service.process(Service.java:42)

运行脚本后会输出合并后的单行:

[2024-05-20 10:05:00] ERROR: Failed to process request | java.lang.NullPointerException |     at com.example.Service.process(Service.java:42)

这样就能精准过滤出包含目标字符串、时间在指定范围内的日志,而且把多行异常合并成了单行,完美解决你之前的问题。

内容的提问来源于stack exchange,提问作者grahul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:01:32