更简洁/高效的正则表达式匹配匹配括号内的字符串

时间:2015-05-15 09:07:49

标签: regex

我想匹配foo出现在select([...])内的字符串,但前提是可能出现的括号匹配在一起。例如。匹配select(((foo)))select(x(())(foo(x))()x((y)x)x())但不匹配select((foo)select(x(foo)y()

我知道,我必须限制嵌套括号的最大数量,我想出了以下正则表达式来解决另外一对括号的问题:

select\((?:
    (?:[^()]*|[^()]*\([^()]*\)[^()]*)*
    foo
    (?:[^()]*|[^()]*\([^()]*\)[^()]*)*
    |
    (?:[^()]*|[^()]*\([^()]*\)[^()]*)*
    \([^()]*foo[^()]*\)
    (?:[^()]*|[^()]*\([^()]*\)[^()]*)*
)\)

这意味着在select([...]) 匹配foo,前面或后面没有或一对括号匹配{{1}在一对括号内,前面或后面没有或一对括号。

有没有人为此提供更整洁的解决方案?

扩展我的正则表达式以解决另外两对括号的问题将如下所示:

foo

其中最缩进的部分基本上是前一个正则表达式,select\((?: (?:[^()]*|[^()]*\((?:[^()]*|[^()]*\([^()]*\)[^()]*)*\)[^()]*)* foo (?:[^()]*|[^()]*\((?:[^()]*|[^()]*\([^()]*\)[^()]*)*\)[^()]*)* | (?:[^()]*|[^()]*\((?:[^()]*|[^()]*\([^()]*\)[^()]*)*\)[^()]*)* \((?: (?:[^()]*|[^()]*\([^()]*\)[^()]*)* foo (?:[^()]*|[^()]*\([^()]*\)[^()]*)* | (?:[^()]*|[^()]*\([^()]*\)[^()]*)* \([^()]*foo[^()]*\) (?:[^()]*|[^()]*\([^()]*\)[^()]*)* )\) (?:[^()]*|[^()]*\((?:[^()]*|[^()]*\([^()]*\)[^()]*)*\)[^()]*)* )\) 部分已扩展为no or one pair of parentheses

我把这最后一个正则表达式放在regex101上:https://www.regex101.com/r/fJ6cR4/1

问题是这个正则表达式(以及更进一步扩展的版本)非常耗时,所以我希望有更好的想法。

2 个答案:

答案 0 :(得分:2)

要简化(并加快)正则表达式,您应该做两件事:

  • rifiutaSingolo()catastrophic backtracking的一个示例。外部重复组应该只有两种选择:一系列非括号内的字符或括号内的这样一个序列:

    (?: [^()]* | [^()]*\([^()]*\)[^()]* )*

    您将非括号内的字符(?: [^()]+ | \([^()]*\) )* 混合到两个备选方案中。

  • 而不是[^()]*,你最好做…foo…|…\(foo\)…,这样你就不必重复冗长的…(?:foo|\(foo\))…事。

使用这两个,你的小表达式变为

我会把这些应用到更大的表达上给你。

答案 1 :(得分:1)

根据Regular-expressions.info

  

如果你想要一个在字符串中找不到任何匹配的正则表达式   包含不平衡的括号,那么你需要使用subroutine call而不是递归。

我尝试根据您的需求调整该网站上的正则表达式:

(?im)^(?![^()]*\(\))[^()\n]*+(\((?>[^()\n]|(?1))*+\)[^()\n]*)++$

请参阅demo

您可以在Sublime Text中使用此正则表达式,遗憾的是,它在Notepad ++中不起作用。

修改

要强制执行匹配的要求,必须以select(开头,包含foo并以) 结尾,您只需添加{{1}在开始时积极向前看:

(?=select\(.*foo.*\)$)

请参阅updated demo