用于匹配括号中所有内容的递归正则表达式(PCRE)

时间:2019-01-11 09:02:39

标签: regex pcre

令我惊讶的是,我不容易找到类似的问题并给出了答案。我想匹配某些功能中的所有内容。这个想法是删除无用的功能。

foo(some (content)) --> some (content)

因此,我试图匹配函数调用中的所有内容,其中可能包含括号。这是我的PCRE正则表达式:

(?<name>\w+)\s*\(\K
(?<e>
     [^()]+
     |
     [^()]*
         \((?&e)\)
     [^()]*
)*
(?=\))

https://regex101.com/r/gfMAIM/1

不幸的是,它不起作用,我也不是很清楚为什么。

3 个答案:

答案 0 :(得分:2)

您的组e模式执行不正确,当前,您仅递归一次e模式一次,它就会匹配深度为1的括号。它需要匹配存在的(...)个子字符串,因此,子例程模式必须位于*+量化组中,甚至可以“简化”到(?<e>[^()]*(?:\((?&e)\)[^()]*)*)

请注意,您的组e模式等于(?<e>[^()]+|\((?&e)\))*[^()]*周围的\((?&e)\)是多余的,因为在当前深度级别,[^()]+替代项将消耗()以外的字符。

此外,您还对Group e模式进行了量化,使其成为repeated capturing group,仅在上一次迭代期间使文本保持匹配。

您可以使用

(?<name>\w+)\s*\(\K(?<e>[^()]*(?:\((?&e)\)[^()]*)*)(?=\))

请参见regex demo

详细信息

  • (?<name>\w+)\s*\(\K-比赛中省略了1个以上的字符字符,0个以上的空格和(
  • (?<e>-组e的开始
    • [^()]*-除()以外的0多个字符
    • (?:-一个非捕获组的开始:
      • \(-一个(字符
      • (?&e)-组e模式已重新出现
      • \)-一个)
      • [^()]*-除()以外的0多个字符
    • )*-重复0次或更多
  • )-e组的结尾
  • (?=\))-)必须紧邻当前位置的右侧。

答案 1 :(得分:1)

以下正则表达式无需执行额外步骤即可进行匹配:

(?<name>\w+)\s*(\((?<e>([^()]*+|(?2))+)\))

请参见live demo here

但这与以下引号字符串中包含不平衡括号的字符串不匹配:

  • foo(bar = ')')
  • foo(bar(john = "(Doe..."))

所以您应该寻找的是:

(?<name>\w+)\s*(\((?<e>([^()'"]*+|"(?>[^"\\]*+|\\.)*"|'(?>[^'\\]*+|\\.)*'|(?2))+)\))

请参见live demo here

正则表达式细目:

  • (?<name>\w+)\s*匹配函数名称和尾随空格
  • (集群开始
    • \(匹配文字(
    • (?<e>开始命名捕获组e
      • (开始捕获#2组
        • [^()'"]*+匹配()'"以外的任何东西
        • |
        • "(?>[^"\\]*+|\\.)*"匹配双引号之间的所有内容
        • |
        • '(?>[^'\\]*+|\\.)*'匹配单引号之间的所有内容
        • |
        • (?2)递归第二个捕获组
      • )+尽可能重复,至少重复一次
    • )捕获组结束
    • \)从字面上匹配)
  • )捕获组结束

答案 2 :(得分:0)

我有没有recursion的简单正则表达式。

(?<=[\w ]{2}\().*(?=\))
到目前为止,

它处理的是不平衡的假体,但它不处理一行上的多个功能。如果您知道函数之间的分隔符,则可以进行处理。例如;(如果是Java代码)。

Variant 2(已针对多项功能更新):

(?<=[\w ]\()[^;\n]*(?=\))

Variant 3(允许;字符串):

(?<=[\w ]\()([^;\n]|".*?")*(?=\))    

Variant 4(转义字符串):

(?<=[\w \n]\()(?:[^;\n"]|(?:"(?:[^"]|\\")*?(?<!\\)"))*(?=\))