我的用例如下:我正在解析一个SQL查询,试图获取一个函数名和发送给该函数的相应参数。这要求我的正则表达式能够找到名称、左括号、内容和右括号。不幸的是,在测试过程中发现它有时过于贪婪,获取了额外的括号,有时却错过了右括号。
下面是我在playground上的测试代码:
func getRegex(name string) string {
return fmt.Sprintf("\\$__%s\\b(?:\\((.*?\\)?)\\))?", name)
}
func main() {
var rawSQL = "(select min(time) from table where $__timeFilter(time))"
rgx, err := regexp.Compile(getRegex("timeFilter"))
if err != nil {
fmt.Println(err)
}
var match = rgx.FindAllStringSubmatch(rawSQL, -1)
fmt.Println(match)
}
以https://go.dev/play/p/4FpZblia7Ks为例
我正在测试的4个案例如下:
(select min(time) from table where $__timeFilter(time) ) OK
(select min(time) from table where $__timeFilter(time)) NOK
select * from foo where $__timeFilter(cast(sth as timestamp)) OK
select * from foo where $__timeFilter(cast(sth as timestamp) ) NOK
这是一个实时regexr版本https://regexr.com/700oh
我来自javascript世界,所以从来没有使用过递归正则表达式,看起来这可能是一个情况?
2条答案
按热度按时间8cdiaqws1#
看起来你的正则表达式有两个主要问题,其中一个比另一个更容易处理:
1.正则表达式在处理递归匹配(如分组左括号和右括号)方面本来就不好,因为它们没有内存。在您的例子中,我认为您已经尝试通过将自己限制在几个特定的情况下来解决这个问题,但正则表达式的贪婪本质在这里对您不利。
1.您不符合右括号前可能有空格的情况。
这两个问题共同导致正则表达式在这两个情况下失败,但也导致第一个情况匹配。
要解决这个问题,在将字符串发送到正则表达式之前,必须对它进行一些预处理:
这将去掉任何外部括号,如果没有内存或额外的子句,正则表达式将无法忽略这些括号。
接下来,需要修改正则表达式,以处理内部函数调用和
$__timeFilter
调用之间可能存在空格的情况:这样做之后,你的正则表达式就可以工作了。你可以在this playground link上找到一个完整的例子。
b0zn9rqh2#
我选择了Woody的答案作为正确答案,尽管我最终不得不走另一条路。所附的测试用例没有包括一些场景,而且我还必须能够提取括号内的参数。因此,这是我的最终解决方案,我手动解析文本,找到括号,并提取它们之间的任何内容:
GoPlayground链接:https://go.dev/play/p/-odWKMBLCBv