如何修正正则表达式以正确匹配带OPTIONS的CREATE TABLE语句
问题
我有如下CREATE TABLE语句:
CREATE TABLE db.my_table ( ts TIMESTAMP OPTIONS (description = "This is 'a' (timestamp)"), id INT64 OPTIONS (description = 'id'), value STRING ) PARTITION BY ts, id CLUSTER BY id OPTIONS (description = 'test_(table)');
需要提取以下字段:db、表名、列定义(即db.my_table后左括号到PARTITION BY前右括号之间的所有内容),以及PARTITION BY的字段、CLUSTER BY的字段和最终的description文本。其中PARTITION BY、CLUSTER BY和OPTIONS子句均为可选,可出现或缺失。
我使用了如下正则表达式:
CREATE TABLE (\w+).(\w+) \(((?s).*)\)(?:\s+PARTITION BY ([^\n\r]+))?(?:\s+CLUSTER BY ([^\n\r]+))?(?:\s+OPTIONS \(description = ((?<Qt>'''|'|")(.*?)\k<Qt>))?;
当没有OPTIONS子句时,正则能正常匹配,比如以下输入:
CREATE TABLE db.my_table ( ts TIMESTAMP OPTIONS (description = "This is 'a' (timestamp)"), id INT64 OPTIONS (description = 'id'), value STRING ) PARTITION BY ts, id CLUSTER BY id;
但存在OPTIONS子句时,正则会错误捕获到OPTIONS的最后一个),导致列定义提取错误,求修正方法。
修正方案
原正则的问题在于((?s).*)是贪婪匹配,会从列定义的左括号开始,一直匹配到整个语句的最后一个右括号,包含了OPTIONS子句里的括号。解决核心是用平衡括号匹配列定义,确保只匹配到列定义对应的闭合右括号。
修正后的正则:
CREATE TABLE (\w+)\.(\w+) \(((?s)(?:[^()]|\((?<depth>)|\)(?<-depth>))*(?(depth)(?!)))\)(?:\s+PARTITION BY ([^\n\r;]+))?(?:\s+CLUSTER BY ([^\n\r;]+))?(?:\s+OPTIONS \(description = ((?<Qt>'''|'|")(.*?)\k<Qt>)\))?;
关键修改点
- 平衡括号匹配列定义:
(?:[^()]|\((?<depth>)|\)(?<-depth>))*(?(depth)(?!))会跟踪括号嵌套深度,只有当括号完全平衡时才停止匹配,避免吃掉后面子句的括号 - 限制PARTITION/CLUSTER BY的匹配范围:将
[^\n\r]+改为[^\n\r;]+,防止匹配到后续的OPTIONS子句或分号 - 完善OPTIONS子句的闭合:给OPTIONS部分的匹配补充了闭合的
\),确保整个子句被正确识别
效果验证
- 带OPTIONS的语句:能准确提取列定义(到第一个平衡右括号),同时正确捕获
PARTITION BY、CLUSTER BY的字段,以及OPTIONS中的description文本 - 不带OPTIONS的语句:依然能正常匹配所有目标字段
内容的提问来源于stack exchange,提问作者sanyi14ka
相关产品推荐
相关产品推荐

