[英]Regular expression/Regex with Java/Javascript: performance drop or infinite loop
我想在这里提交一个我想要了解的非常具体的性能问题。
我正在尝试用正则表达式验证自定义合成器。 通常,我没有遇到性能问题,所以我喜欢使用它。
正则表达式:
^(\{[^\][{}(),]+\}\s*(\[\s*(\[([^\][{}(),]+\s*(\(\s*([^\][{}(),]+\,?\s*)+\))?\,?\s*)+\]\s*){1,2}\]\s*)*)+$
一个有效的synthax:
{Section}[[actor1, actor2(syno1, syno2)][expr1,expr2]][[actor3,actor4(syno3, syno4)][expr3,expr4]]
你可以在这里找到正则表达式和测试文本: https : //regexr.com/3jama
我希望足够了,我不知道如何解释我想要比正则表达式更匹配的东西;-)。
将正则表达式应用于有效文本并不需要花费太多,它几乎是即时的。 但是当涉及到特定的无效文本案例时,regexr应用程序会挂起。 它不是特定于regexr应用程序,因为我也遇到了我自己的java代码或javascript代码的戏剧性表现。
因此,我的需求是验证用户正在键入文本。 我甚至可以想象在点击时验证文本,但是如果用户提交的文本结构如下所示,或者另一个产生相同性能下降,则我无法承担该应用程序的挂起。
只需从测试文本中删除尾随的“]”字符即可
因此,提高性能下降的无效文本变为:
{Section}[[actor1, actor2(syno1, syno2)][expr1,expr2]][[actor3,actor4(syno3, syno4)][expr3,expr4
另一个无效测试可能是,并且没有性能下降:
{Section}[[actor1, actor2(syno1, syno2)][expr1,expr2]][[actor3,actor4(syno3, syno4)][expr3,expr4]]]
如果一个正则表达的大师能够解释我做错了什么,或者为什么我的用例不适合正则表达式,我会很高兴的。
这个答案适用于您评论中的精简正则表达式:
^(\{[^\][{}(),]+\}(\[(\[([^\][{}(),]+(\(([^\][{}(),]+\,?)+\))?\,?)+\]){1,2}\])*)+$
您的原始模式的问题类似。
你正面临着灾难性的回溯。 每当正则表达式引擎无法完成匹配时,它就会回溯到字符串中,试图找到将模式与某些子字符串匹配的其他方法。 如果你有很多模糊的模式,特别是如果它们出现在重复内部,测试所有可能的变化需要花费很多时间。 请参阅链接以获得更好的解释。
您使用的子模式之一是以下(为了更好的可视化而采用多行模式):
([^\][{}(),]+
(\(
([^\][{}(),]+\,?)+
\))?
\,?)+
这应该匹配像actor4(syno3, syno4)
这样的字符串。 将这种模式稍微缩小,你得到([^\\][{}(),]+,?)+
。 如果删除了,?
从它,你得到([^\\][{}(),]+)+
这是一个营养回溯的开门,因为字符串可以用这种模式以很多不同的方式匹配。
我得到你试图用这个模式做的事情 - 匹配一个标识符 - 以及用逗号分隔的其他其他标识符。 然而,正确的方法是: ([^\\][{}(),]+(?:,[^\\][{}(),]+)*)
。 现在没有一种模糊的方式可以回溯到这种模式。
为上面显示的整个模式执行此操作(是的,还有另一个可选的逗号,必须推出)并将其插回到您的完整模式我得到:
^(\{[^\][{}(),]+\}(\[(\[([^\][{}(),]+(\(([^\][{}(),]+(?:,[^\][{}(),]+)*)\))?(?:\,[^\][{}(),]+(\(([^\][{}(),]+(?:,[^\][{}(),]+))*\))?)*)\]){1,2}\])*)+$
不走回头路灾难性了 。
您可能希望自己帮忙并将其拆分为子模式,这些子模式可以使用实际源中的字符串连接在一起,或者如果使用PCRE模式则使用定义。
请注意,一些正则表达式引擎允许使用原子组和占有量词,进一步帮助避免不必要的回溯。 由于您在标题中使用了不同的语言,因此您必须自行检查,哪一种可用于您选择的语言。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.