python - 如何使用正则表达式按顺序提取文本?
问题描述
我正在研究一个 python 流脚本。它基本上解析SQL语句并获取目标表和源表。例子
CREATE TABLE TAR_TAB1 AS
SELECT * FROM SRC_TAB1 JOIN SRC_TAB2
CREATE TABLE TAR_TAB2 AS
SELECT * FROM SRC_TAB3 JOIN SRC_TAB4
INSERT INTO TAR_TAB3 AS
SELECT * FROM SRC_TAB5 JOIN SRC_TAB6
我写了正则表达式
target = re.findall(r'\w+(?=\s+AS)', data)
source = re.findall(r'(?:FROM|JOIN)\s*([^\s]+), data)
结果如预期,
target list contains, TAR_TAB1, TAR_TAB2, TAR_TAB3
source list contains, SRC_TAB1, SRC_TAB2, SRC_TAB3, SRC_TAB4, ETC
如何获得像列表或数据帧一样的输出,最好是数据帧,因此提取流程不会受到干扰。
target source
TAR_TAB1 SRC_TAB1
TAR_TAB1 SRC_TAB2
TAR_TAB2 SRC_TAB3
TAR_TAB2 SRC_TAB4
TAR_TAB3 SRC_TAB5
TAR_TAB4 SRC_TAB6
解决方案
这种方法使用 pyparsing 来实际解析 SQL 语句(在您在示例中显示的子集语法内):
import pyparsing as pp
ppc = pp.pyparsing_common
ident = ppc.identifier
CREATE, INSERT, INTO, TABLE, AS, SELECT, FROM, JOIN = \
map(pp.CaselessKeyword, "CREATE INSERT INTO TABLE AS SELECT FROM JOIN".split())
select_stmt = (SELECT
+ (pp.delimitedList(ident) | '*')("columns")
+ FROM
+ ((ident + JOIN.suppress() + ident) | ident)("tables"))
src_target_stmt = ((CREATE + TABLE | INSERT + INTO)("action")
+ ident("target")
+ AS
+ pp.Group(select_stmt)("source"))
tests = """
CREATE TABLE TAR_TAB1 AS SELECT * FROM SRC_TAB1 JOIN SRC_TAB2
CREATE TABLE TAR_TAB2 AS SELECT * FROM SRC_TAB3 JOIN SRC_TAB4
INSERT INTO TAR_TAB3 AS SELECT COL1,COL2 FROM SRC_TAB5 JOIN SRC_TAB6
"""
# useful for debugging
#src_target_stmt.runTests(tests)
# dump parsed values out as CSV output
for t in tests.splitlines():
if not t.strip():
continue
result = src_target_stmt.parseString(t)
target = result.target
action = result.action[0]
for src in result.source.tables:
print("{},{},{}".format(action, target, src))
印刷:
CREATE,TAR_TAB1,SRC_TAB1
CREATE,TAR_TAB1,SRC_TAB2
CREATE,TAR_TAB2,SRC_TAB3
CREATE,TAR_TAB2,SRC_TAB4
INSERT,TAR_TAB3,SRC_TAB5
INSERT,TAR_TAB3,SRC_TAB6
随着您继续您的项目并发现新的需求(需要提取本示例中所示的 SQL 操作,或者您发现需要在解析中理解的 SQL 构造的其他变体),扩展解析器将更容易且更易于维护而不是扩展正则表达式。
推荐阅读
- typescript - 使用打字稿检查 GraphQLObjectType 中的字段
- graphql - 使用 ariadne 服务器时如何合并多个 graphql 模式文件?
- python - 复制文件。缺少 1 个必需的位置参数
- python - 向所有类实例添加常量变量
- go - Golang 类型嵌入工具
- spi - Zephyr RTOS问题中的QSPI片选管脚控制与配置
- python - Django forms.DateTimeField 更改输入类型
- django - 如何使用ajax提交带有输入文件的表单
- c# - C# - 如何将 GetFromJsonAsync 的结果分配给变量,并在不重复调用 GET 请求的情况下使用它?
- django - 具有多个模型的外键?