首页 > 解决方案 > Rexgex:如何在括号之间捕获任何内容,除非它在方括号之间

问题描述

我需要一个正则表达式来捕获括号之间的任何内容,除非它在以下模式之间,一个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

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

“我是一个(测试)S[ 但我是(没有被抓住)],抓住(我(如果可以的话))”

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

标签: javascriptregexbrackets

解决方案


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

请参阅此处使用的正则表达式

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

这是如何工作的:

  • (?<!S\[[^\]]+)消极的后视确保以下不匹配:
    • S\[S[从字面上匹配
    • [^\]]+匹配除]一次或多次以外的任何字符
  • \((从字面上匹配
  • (?:[^()]|\([^)]*\))+匹配以下任一选项一次或多次
    • [^()]匹配除(and以外的任何字符)
    • \([^)]*\)match ,然后是除任意次数之外的(任何字符,然后))
  • \))从字面上匹配

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

这个答案解释了如何在不同的正则表达式引擎中平衡括号(如果你使用 XRegExp,包括 JavaScript)。

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

PCRE见这里

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

.NET见这里

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

编辑

更改后视中的量词+*防止它匹配以下情况S[(...)]

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

推荐阅读