简化AWK实现:匹配字符串后检查后续X行不含指定字符串
Hey,针对你要简化AWK脚本实现「匹配目标字符串后检查后续X行不含指定内容」的需求,结合你给出的Hikari配置日志,我整理了几个简洁实用的方案:
通用版AWK脚本(适配任意日志格式)
这个脚本可以灵活定义匹配的初始字符串、需要排查的禁止字符串,以及要检查的后续行数:
awk -v target="autoCommit......................true" \ -v check_str="connectionInitSql...............null" \ -v check_lines=2 ' # 匹配到目标行时,开启检查状态 $0 ~ target { is_checking = 1 line_counter = 0 found_forbid = 0 } # 处于检查状态时,逐行处理 is_checking { line_counter++ # 如果遇到禁止字符串,标记为已发现 if ($0 ~ check_str) found_forbid = 1 # 检查完指定行数后,输出结果并重置状态 if (line_counter > check_lines) { if (!found_forbid) { print "符合条件:匹配行后" check_lines "行未出现指定字符串" # 也可以输出匹配的初始行:print "匹配行:" target_line } is_checking = 0 found_forbid = 0 } } ' your_log_file.log
参数说明:
target:你要匹配的初始字符串(比如示例中的autoCommit......................true)check_str:需要确保后续行不包含的字符串(比如connectionInitSql...............null)check_lines:需要检查的后续行数(比如示例中的2)
针对Hikari日志的优化版
因为你的日志有固定格式(时间 [线程] 级别 类名 - 配置项),我们可以通过匹配配置项的键名来更精准地定位,避免因格式细节(比如点的数量)导致的匹配问题:
awk -v match_key="autoCommit" \ -v forbid_key="connectionInitSql" \ -v check_lines=2 ' # 匹配包含目标配置键的行 /- '"$match_key"'/ { is_checking = 1 line_counter = 0 found_forbid = 0 # 保存匹配到的初始行(可选) match_line = $0 } is_checking { line_counter++ if (/- '"$forbid_key"'/) found_forbid = 1 if (line_counter > check_lines) { if (!found_forbid) { # 输出匹配的初始行,明确符合条件 print match_line " → 后续" check_lines "行无" forbid_key ",符合要求" } is_checking = 0 } } ' your_log_file.log
这个版本更健壮,比如不管autoCommit后面有多少个点,只要配置键是autoCommit就能匹配到,不用纠结格式细节。
自定义输出调整
如果只需要输出满足条件的初始行,直接把print语句改成print match_line即可;如果要输出不符合条件的行(即匹配后出现了禁止字符串),可以在found_forbid=1时直接输出提示并重置状态。
这些脚本用AWK的状态机逻辑实现,比嵌套grep的写法更高效,尤其是处理大日志文件时,不需要多次遍历文件,性能优势很明显。
内容的提问来源于stack exchange,提问作者Haimon
相关产品推荐
相关产品推荐

