python提取mybatis日志sql

import re

def parse_mybatis_log(log_path, output_sql_path, filter_keyword: str = None):
    preparing_pattern = re.compile(r'Preparing:\s+(.*?)(?=\s+org\.apache\.ibatis|$)')
    param_pattern = re.compile(r'Parameters:\s+(.*?)\s+org\.apache\.ibatis')
    param_item_pattern = re.compile(r'(.*?)\((String|Integer|Long|Double|Date|BigDecimal)\)')

    last_prepare_sql = None
    output_lines = []
    match_count = 0

    with open(log_path, 'r', encoding='utf-8') as log_file:
        for line in log_file:
            line = line.strip()
            # 捕获SQL模板
            prepare_match = preparing_pattern.search(line)
            if prepare_match:
                raw_sql = prepare_match.group(1).strip()
                if filter_keyword and filter_keyword.lower() not in raw_sql.lower():
                    last_prepare_sql = None
                    continue
                last_prepare_sql = raw_sql
                continue

            # 解析参数并填充SQL
            param_match = param_pattern.search(line)
            if param_match and last_prepare_sql is not None:
                try:
                    param_raw = param_match.group(1)
                    param_list = param_item_pattern.findall(param_raw)
                    fill_params = []

                    for val, typ in param_list:
                        # 先去掉前面的逗号和空格
                        val = val.strip().lstrip(',').strip()
                        # 空参数填充NULL
                        if not val:
                            fill_params.append("NULL")
                        elif typ == "String":
                            fill_params.append(f"'{val}'")
                        else:
                            fill_params.append(val)

                    # 校验占位符与参数数量一致
                    placeholder_count = last_prepare_sql.count("?")
                    if len(fill_params) != placeholder_count:
                        print(f"警告:参数数量不匹配,占位符{placeholder_count}个,实际参数{len(fill_params)}个,跳过本条SQL")
                        last_prepare_sql = None
                        continue

                    # 逐个替换 ?
                    final_sql = last_prepare_sql
                    for p in fill_params:
                        final_sql = final_sql.replace("?", p, 1)

                    output_lines.append(final_sql + ";\n")
                    match_count += 1
                except Exception as e:
                    print(f"解析异常,行内容:{line},错误信息:{str(e)}")
                last_prepare_sql = None

    # 输出到文件
    with open(output_sql_path, 'w', encoding='utf-8') as f_out:
        f_out.writelines(output_lines)

    print(f"解析完成!共匹配 {match_count} 条目标SQL,输出文件:{output_sql_path}")


if __name__ == "__main__":
    # 配置
    LOG_FILE_PATH = "app.log"
    OUTPUT_SQL_PATH = "result_insert.sql"
    # 过滤只提取 tablename 的insert语句
    FILTER_TEXT = "insert into tablename"
    # FILTER_TEXT = None  # 取消过滤,提取所有SQL

    parse_mybatis_log(
        log_path=LOG_FILE_PATH,
        output_sql_path=OUTPUT_SQL_PATH,
        filter_keyword=FILTER_TEXT
    )

 

posted @ 2026-06-22 14:15  Liu66~  阅读(4)  评论(0)    收藏  举报