首页 > 解决方案 > 如何使用正则表达式按顺序提取文本?

问题描述

我正在研究一个 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

标签: pythonregex

解决方案


这种方法使用 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 构造的其他变体),扩展解析器将更容易且更易于维护而不是扩展正则表达式。


推荐阅读