加快正则表达

时间:2019-02-14 09:33:18

标签: java regex performance

这是一个正则表达式,用于从SQL语句中提取表名:

[`'"]

它匹配一个令牌,可以选择将其括在private organizationArray: Array<string>; const claims = jwtDecode<any>(token); this.claims = { email: claims['http://schemas.xmlsoap.org/ws/***/**/***/claims/emailaddress'], id: claims['http://schemas.xmlsoap.org/ws/***/**/*****/claims/sid'], name: claims['http://schemas.xmlsoap.org/ws/***/**/****/claims/name'], expires: new Date(claims['exp'] * 1000), }; this.organizationArray = claims['http://schemas.*****.**/**/****/**/*******/claims/organization']; console.log( this.organizationArray.length) 中,并在其前加上由空格包围的FROM等。除了没有前导空格的UPDATE以外。

我们执行许多正则表达式,这是最慢的正则表达式,我不确定为什么。 SQL字符串的最大大小为4k,而在2.2GHz i7 MBP上,执行时间最差的是0.35ms。

这是一个缓慢的输入示例:https://pastebin.com/DnamKDPf

我们可以做得更好吗?如果有问题,将其拆分为多个正则表达式也是一种选择。

3 个答案:

答案 0 :(得分:1)

Regex优化是一个非常复杂的主题,应借助一些工具来完成。例如,我喜欢Regex101,它可以为我们计算Regex引擎为使patternpayload匹配而必须执行的步骤数。对于您的pattern和给定的示例,它将打印:

1 match, 22976 steps (~19ms)

您总是可以做的第一件事就是将相似的部分归为一组。例如,FROMINTOJOIN看起来很相似,因此我们可以如下编写正则表达式:

(?:\s(?:FROM|INTO|JOIN)\s|\sNEXTVAL[\s\W]*|^UPDATE\s)[\s`'"]*([\w\.-_]+)

对于上面的示例Regex101,打印:

1 match, 15891 steps (~13ms)

尝试找到一些解释和优化Regex的在线工具,例如myregextester,并计算引擎需要执行的步骤。

答案 1 :(得分:1)

因为比赛通常都快要结束了,所以一种可能性是基本上从结尾开始并回溯,而不是从起点开始并向前回溯,

--no-cache-dir

https://regex101.com/r/SO7M87/1/(154个步骤)

虽然在存在匹配项时这可能会快很多,但在没有匹配项时只是适度的改进,因为模式必须一直追溯到开始(~9000步骤~23k个步骤)

答案 2 :(得分:1)

有一个rule of thumb

  

如果存在边界,请勿让引擎尝试匹配每个单个字符。

尝试以下正则表达式(在给定的输入字符串上执行约2500个步骤):

(?!FROM|INTO|NEXTVAL|UPDATE|JOIN)\S*\s*|\w+\W*(\w[\w\.-]*)

Live demo

注意:您需要的是第一个捕获组。

根据评论,最终的正则表达式(比以前的整洁慢一点):

(?!(?:FROM|INTO|NEXTVAL|UPDATE|JOIN)\b)\S*\s*|\b(?:NEXTVAL\W*|\w+\s[\s`'"]*)([\[\]\w\.-]+)
相关问题