如何使用Python re模块提取文本中所有多行SQL SELECT语句块
如何使用Python re模块提取文本中所有多行SQL SELECT语句块
我来帮你搞定这个提取多行SELECT块的问题!用正则处理SQL确实得注意各种细节,比如多行换行、带UNION的联合查询,还有不同的语句结尾方式(分号/括号),下面我一步步给你演示怎么做:
首先先明确我们要覆盖的几种场景:
- 单行的简单SELECT语句(比如
select p.value_n, p.enabled from proper p;) - 跨多行、带WHERE条件的SELECT语句
- 被括号包裹的联合查询块(比如
(select ... union all select ...))
直接上可运行的代码,我会逐段解释:
import re # 你的原始SQL文本 sql_que = """ select p.value_n, p.enabled from proper p; select p.value_n, p.enabled from proper p where p.property_name = 'PROP1'; (select p.value_n, p.enabled from proper p where p.property_name = 'PROP1' union all select p.value_n, p.enabled from proper p where p.property_name = 'PROP2' ) """ # 核心正则表达式 # 拆解下这个pattern的关键部分: # (?i):忽略大小写,不管是大写SELECT还是小写select都能匹配 # (?:...):非捕获组,把两种匹配规则打包,不会单独返回组内的子匹配 # \(select.*?\):匹配括号包裹的SELECT块,从(select开始到对应的)结束 # |:逻辑或,匹配后面的普通SELECT语句规则 # select.*?;:匹配从select开头到分号结束的常规SELECT语句 # re.DOTALL:让正则中的.能匹配换行符,这样多行内容也能被完整捕获 pattern = r'(?i)(?:\(select.*?\)|select.*?;)' matches = re.findall(pattern, sql_que, flags=re.DOTALL) # 清理匹配结果:把多余的换行、连续空格换成单个空格,让输出更整洁 cleaned_selects = [] for match in matches: # 先去除语句前后的空白字符 stripped_stmt = match.strip() # 把所有连续的空白(换行、空格、制表符)统一换成单个空格 cleaned_stmt = re.sub(r'\s+', ' ', stripped_stmt) cleaned_selects.append(cleaned_stmt) # 打印提取结果 for idx, stmt in enumerate(cleaned_selects, 1): print(f"第{idx}个SELECT块:") print(stmt) print("-" * 50)
运行这段代码后,你会得到三个完整的SELECT块,包括那个带UNION ALL的联合查询,完全符合你的需求!
最后提个小提醒:这个正则是针对你的示例场景写的,如果你的实际SQL里有嵌套括号(比如SELECT里的子查询还有多层括号),或者字符串里包含分号/括号(比如WHERE name = 'abc;def'),那这个简单正则就会失效——毕竟正则没法真正理解SQL语法,只能做模式匹配。
如果你的实际场景更复杂,比如有嵌套子查询、字符串内的特殊符号,我更推荐用专门的SQL解析库sqlparse,它能真正读懂SQL语法,比正则靠谱多了。但如果你的场景和示例一样简单,上面的正则完全够用啦!




