上周帮朋友修一个自动备份脚本,他用 Python 写的,逻辑看着没问题,但每次执行到解析 SQL 备份语句时就报错。翻日志发现是正则匹配乱了——把 WHERE id = 1 AND status > 0 里的 AND 当成独立关键字切开了,结果条件拼错,备份出来的数据缺了一大块。
正则不是万能的
很多人写备份工具时习惯用正则提取 SQL 片段、JSON 字段或配置文件里的关键值,比如:
re.findall(r"SELECT\s+(.*?)\s+FROM", sql)这种写法在简单语句里跑得飞快,可一旦遇到嵌套括号、引号内含关键字(比如 SELECT 'AND' as name FROM t),立马失效。这不是 bug,是正则本身的能力边界。换个思路:让程序“读懂”结构
语法树分析(Parsing Tree Analysis)就是让程序像人一样,先识别词法单元(token),再按语法规则组装成树状结构。比如这句:
INSERT INTO users (name, age) VALUES ('张三', 28);经过语法树分析后,会生成类似这样的结构:{
"type": "insert_statement",
"table": "users",
"columns": ["name", "age"],
"values": ["'张三'", "28"]
}所有字段名、值、括号层级都清清楚楚,不会被单引号或空格干扰。备份场景里怎么用?
我们写了个小工具,专门校验备份前的 SQL 脚本是否安全:先用 sqlparse 库做语法树解析,再遍历树节点,过滤掉 DROP、TRUNCATE 这类危险操作,同时检查 WHERE 子句是否存在(防止全表覆盖)。代码片段如下:
import sqlparse
from sqlparse.sql import IdentifierList, Identifier, Where
def safe_backup_check(sql):
parsed = sqlparse.parse(sql)[0]
for token in parsed.tokens:
if token.is_group and hasattr(token, 'tokens'):
if any('DROP' in str(t).upper() for t in token.tokens):
raise ValueError("检测到 DROP 操作,拒绝执行")
if isinstance(token, Where):
return True # 有 WHERE 才放行
return False上线后,团队误删生产库的事故降为零。语法树分析不是高深理论,它是让备份脚本从“碰运气”走向“可验证”的关键一步——尤其当你每天要处理上百个不同格式的 SQL、JSON、YAML 配置时,靠人眼 review 或正则硬怼,迟早出事。