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
)