Python正则匹配SQL脚本中CTAS语句并保留注释的改造需求
保留注释的CTAS语句识别与改造方案
核心思路
不要先全局移除注释,而是先标记脚本中的所有注释区域(单行、多行),仅在非注释区域匹配并改造CTAS语句,最后将原注释和改造后的代码按原顺序合并,确保注释完全保留。
具体实现步骤
- 识别注释与字符串区域:用正则匹配单行注释(
--到行尾)、多行注释(/* ... */)以及字符串(单/双引号包裹内容),避免误将字符串内的注释符号判定为注释。 - 分割与处理脚本:将脚本拆分为注释段、字符串段和非注释段,只对非注释段执行CTAS匹配和改造。
- 匹配CTAS语句:编写覆盖常见语法的正则(如支持临时表、
IF NOT EXISTS、大小写不敏感),定位需要改造的CTAS语句并执行修改。 - 合并内容:将处理后的非注释段与原注释段、字符串段按原顺序拼接,输出完整脚本。
示例Python代码
import re def process_ctas_preserve_comments(sql_script): # 正则:匹配多行注释、单行注释、字符串(优先匹配,避免误判) pattern = re.compile( r'(/\*.*?\*/)|(--[^\n]*(\n|$))|(\'[^\']*?\'|"[^"]*?")', re.DOTALL | re.IGNORECASE ) processed_parts = [] current_pos = 0 for match in pattern.finditer(sql_script): # 处理匹配前的非注释内容 if match.start() > current_pos: non_comment_segment = sql_script[current_pos:match.start()] # 改造非注释区域的CTAS:示例为表名添加后缀_NEW modified_segment = re.sub( r'CREATE\s+(TEMPORARY|TEMP)?\s*(IF NOT EXISTS)?\s*TABLE\s+(\w+)\s+AS\s+(SELECT.*?)(?=\s*(;|CREATE|$))', r'CREATE \1\2 TABLE \3_NEW AS \4', non_comment_segment, flags=re.DOTALL | re.IGNORECASE ) processed_parts.append(modified_segment) # 添加原注释或字符串内容(不修改) processed_parts.append(match.group()) current_pos = match.end() # 处理最后一段非注释内容 if current_pos < len(sql_script): final_non_comment = sql_script[current_pos:] modified_final = re.sub( r'CREATE\s+(TEMPORARY|TEMP)?\s*(IF NOT EXISTS)?\s*TABLE\s+(\w+)\s+AS\s+(SELECT.*?)(?=\s*(;|CREATE|$))', r'CREATE \1\2 TABLE \3_NEW AS \4', final_non_comment, flags=re.DOTALL | re.IGNORECASE ) processed_parts.append(modified_final) return ''.join(processed_parts) # 测试用例 test_sql = """ -- 初始化表 CREATE TABLE t1 AS SELECT id, name FROM raw_data; /* 临时表用于中间计算 支持跨多行的CTAS */ CREATE TEMP TABLE temp_data AS SELECT id, SUM(value) FROM raw_data GROUP BY id; CREATE TABLE t2 AS SELECT * FROM temp_data; -- 这是语句末尾的注释 """ print(process_ctas_preserve_comments(test_sql))
关键注意事项
- 正则优先级:必须优先匹配字符串和注释,防止把字符串内的
--或/*误判为注释。 - 语法兼容性:CTAS正则要覆盖SQL的常见变体,比如临时表关键字、
IF NOT EXISTS、换行写法等。 - 边界处理:注意CTAS语句的结束边界(分号、下一个CREATE语句或脚本结尾),避免匹配不完整。
内容的提问来源于stack exchange,提问作者Leo
相关产品推荐
相关产品推荐

