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

基于PyParsing的Syslog解析求助:适配FortiSIEM格式

Syslog解析器修复:解决PyParsing解析报错与输出为空问题

问题背景

需开发Syslog解析器,将含类JSON键值对的Syslog转换为FortiSIEM兼容的TXT文件,但现有PyParsing脚本出现两类报错:

  • 解析日志行提示Expected ' ', found '2022'
  • 解析空行提示Expected '<'
    且输出文件为空。示例日志格式:

<140>1 2022-05-02T08:31:22.478Z platform dataexport - syslog_variation - {"key"=value, info:{"key"=value, "key"=value, "key"=value}, info2:{"key"=value, "key"=value},"key"=value}

期望输出格式:

<140>1 2022-05-02T08:31:22.478Z platform dataexport - syslog_variation -
key=value
info.key=value
info2.key=value
...

错误原因分析

  1. 头部解析逻辑错误:原脚本用CharsNotIn("\n")定义msgid,未正确处理头部字段间的空格分隔;version等字段的Suppress(" ")写法无法适配多空格场景,导致头部解析失败。
  2. 空行未过滤:脚本未跳过空行,空行无<开头触发解析报错。
  3. 不支持嵌套结构:原脚本无法解析info:{...}这类嵌套对象,且未处理类JSON中混用的:和=分隔符。
  4. 输出逻辑错误:直接写入PyParsing的ParseResults对象会触发类型错误,且未按要求拆分头部与扁平化键值对。

修复后的脚本

from pyparsing import (
    Word, Suppress, alphanums, CharsNotIn, ZeroOrMore, Dict,
    White, Regex, Forward, Group, delimitedList
)

# 定义Syslog头部字段
priority = Suppress("<") + Word(alphanums) + Suppress(">")
version = Word(alphanums)
timestamp = Regex(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z")
hostname = Word(alphanums + "-.")
appname = Word(alphanums + "-")
procid = Word(alphanums + "-") | Suppress("-")
msgid = Word(alphanums + "-") | Suppress("-")

# 组合头部,处理字段间任意空格
header = (
    priority + Suppress(White()) +
    version + Suppress(White()) +
    timestamp + Suppress(White()) +
    hostname + Suppress(White()) +
    appname + Suppress(White()) +
    procid + Suppress(White()) +
    msgid
)

# 定义嵌套键值对解析规则
key = Word(alphanums + "_")
value = Forward()
simple_value = CharsNotIn("{,}\n ")
nested_obj = Suppress("{") + delimitedList(Group(key + (Suppress("=") | Suppress(":")) + value)) + Suppress("}")
value << (simple_value | nested_obj)

# 顶层键值对解析
pair = Group(key + (Suppress("=") | Suppress(":")) + value)
kv_pairs = Suppress("{") + delimitedList(pair) + Suppress("}")

# 完整消息格式
message = header + Suppress(White()) + kv_pairs

# 扁平化嵌套键值对
def flatten_kv(pairs, parent_key=""):
    flat = []
    for key_val in pairs:
        current_key = f"{parent_key}.{key_val[0]}" if parent_key else key_val[0]
        if isinstance(key_val[1], list):
            flat.extend(flatten_kv(key_val[1], current_key))
        else:
            flat.append(f"{current_key}={key_val[1]}")
    return flat

# 处理输入输出文件
with open("syslog.txt", "r") as input_file, open("syslog_output.txt", "w") as output_file:
    for line_num, line in enumerate(input_file, 1):
        line = line.strip()
        if not line:
            continue  # 跳过空行
        try:
            parsed = message.parseString(line, parseAll=True)
            # 拼接头部字符串
            header_str = " ".join(parsed[:7])
            # 提取并扁平化键值对
            kv_list = parsed[7:]
            flat_kv = flatten_kv(kv_list)
            
            # 按要求格式写入
            output_file.write(f"{header_str}\n")
            output_file.write("\n".join(flat_kv) + "\n\n")
            
        except Exception as e:
            print(f"Line {line_num} parse failed: {line} | Error: {e}")
            continue

关键修复说明

  1. 头部解析优化:用Suppress(White())处理任意空格,正则精准匹配RFC3339格式时间戳,支持-作为procid/msgid的占位符。
  2. 空行过滤:添加判断跳过空行,避免无效解析报错。
  3. 嵌套结构支持:通过Forward()实现递归解析嵌套对象,兼容:和=两种键值分隔符。
  4. 扁平化处理:新增函数将嵌套键值对转为parent.key=value格式,适配FortiSIEM的解析需求。
  5. 输出逻辑修正:正确拼接头部与扁平化键值对,确保输出格式符合要求。

内容的提问来源于stack exchange,提问作者Filipe Gonçalves

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 02:27:51