正则表达式:如何捕捉括号之间的任何内容,除非它在方括号之间

Rexgex : How to catch anything between parenthesis except when its between square brackets

我需要一个正则表达式来捕获括号之间的任何内容,除非它位于以下模式之间,一个 S 字符后跟方括号:

S[]

比如这句话:

I am a (test) S[ but i am (not catched)], catch (me (if you can))
       ^^^^^^                                   ^^^^^^^^^^^^^^^^^   # should be matched
              ^^^^^^^^^^^^^^^^^^^^^^^^^^                            # should not be matched

它还应该捕获嵌套的括号。

我尝试使用各种示例使其工作,但我得到的最接近的是这个:

(?![^S\[]*\])\(([^()]*|\(([^()]*|\(([^()]*|\([^()]*\))*\))*\))*\)?

=> 但当您从测试句子中删除 S 时它会失败。

知道怎么做吗?

编辑:应该像这种情况一样匹配,但考虑到 S:https://regex101.com/r/WzECSS/1

编辑:这个应该可以解决问题:(?<!S\[[^\]]+)\((?:[^()]|\([^)]*\))+\)谢谢@ctwheels

编辑:当您将括号直接放在方括号之后时,前面的正则表达式会失败,例如:

"I am a (test) S[( but i am (not catched)], catch (me (if you can))"

有没有人知道如何解决这个问题。谢谢。

您可以在 ECMA2018+(V8 引擎或更高版本)中使用以下正则表达式。以前的版本不支持可变长度回顾。

See regex in use here

(?<!S\[[^\]]+)\((?:[^()]|\([^)]*\))+\)

这是如何工作的:

  • (?<!S\[[^\]]+) 否定后视确保以下内容不匹配:
    • S\[ 按字面意思匹配 S[
    • [^\]]+ 匹配除 ] 之外的任何字符一次或多次
  • \( 按字面意思匹配 (
  • (?:[^()]|\([^)]*\))+ 匹配以下任一选项一次或多次
    • [^()] 匹配除 ()
    • 之外的任何字符
    • \([^)]*\) 匹配 (,然后匹配 ) 以外的任何字符任意次数,然后 )
  • \) 按字面意思匹配 )

但是请注意,这仅匹配两个括号的深度(一组与另一组嵌套)。由于当前不支持递归和其他标记,因此您无法 轻松地 平衡 JavaScript 的正则表达式引擎中的括号。

This answer 解释了如何在不同的正则表达式引擎中平衡括号(如果您使用 XRegExp,则包括 JavaScript)。

其他语言的一些实现示例 - 在 JavaScript 中不可能,因为它不包括递归、控制动词、平衡组等:

PCRE: See here

S\[[^]]*\](*SKIP)(*FAIL)|\((?:[^()]|(?R))*\)

.NET: See here

(?<!S\[[^\]]+)\((?:[^()]|(?<p>\()|(?<-p>\)))+(?(p)(?!))\)

编辑

将 lookbehind 中的量词 + 更改为 * 可防止它匹配 S[(...)]:

的大小写
(?<!S\[[^\]]*)\((?:[^()]|\([^)]*\))+\)