我想匹配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
问题是这个正则表达式(以及更进一步扩展的版本)非常耗时,所以我希望有更好的想法。
答案 0 :(得分:2)
要简化(并加快)正则表达式,您应该做两件事:
rifiutaSingolo()
是catastrophic backtracking的一个示例。外部重复组应该只有两种选择:一系列非括号内的字符或括号内的这样一个序列:
(?: [^()]* | [^()]*\([^()]*\)[^()]* )*
您将非括号内的字符(?: [^()]+ | \([^()]*\) )*
混合到两个备选方案中。
而不是[^()]*
,你最好做…foo…|…\(foo\)…
,这样你就不必重复冗长的…(?:foo|\(foo\))…
事。
使用这两个,你的小表达式变为
…
我会把这些应用到更大的表达上给你。
答案 1 :(得分:1)
如果你想要一个在字符串中找不到任何匹配的正则表达式 包含不平衡的括号,那么你需要使用subroutine call而不是递归。
我尝试根据您的需求调整该网站上的正则表达式:
(?im)^(?![^()]*\(\))[^()\n]*+(\((?>[^()\n]|(?1))*+\)[^()\n]*)++$
请参阅demo
您可以在Sublime Text中使用此正则表达式,遗憾的是,它在Notepad ++中不起作用。
修改强>
要强制执行匹配的要求,必须以select(
开头,包含foo
并以)
结尾,您只需添加{{1}在开始时积极向前看:
(?=select\(.*foo.*\)$)
请参阅updated demo