带有嵌套括号前文本的递归正则表达式

5

我有以下文本

$text = 'This is a test to see if something(try_(this(once))) works';

我需要从文本中使用正则表达式获取something(try_(this(once)))。 我遇到了以下问题:

  • 我的嵌套不会保持不变,我的文本可以是:

    • something(try_(this(once))) 或者
    • something(try_this(once)) 或者
    • something(try_thisonce)

我尝试了网站上找到的许多正则表达式,但无法使其工作。 这是我最接近的实现:

示例1:

$text = 'This is a test to see if something(try_(this(once))) works';
$output = preg_match_all('/(\(([^()]|(?R))*\))/', $text, $out);
?><pre><?php var_dump($out[0]); ?></pre><?php   

这将输出:

array(1) {
  [0]=>
  string(18) "(try_(this(once)))"
}

无论我在哪里添加单词something(例如 '/something(\(([^()]|(?R))*\))/''/(\something(([^()]|(?R))*\))/'),都会得到一个空数组或NULL

示例2

$text2 = 'This is a test to see if something(try_(this(once))) works';
$output2 = preg_match_all('/something\((.*?)\)/', $text2, $out2);
?><pre><?php var_dump($out2[0]); ?></pre><?php  

使用这段代码,我得到的是单词something

array(1) {
  [0]=>
  string(25) "something(try_(this(once)"
}

但是表达式在第一个闭合括号)后停止并返回,这是预期的,因为这不是递归表达式。
如何递归匹配并返回带有单词something的嵌套括号的第一个开括号(之前的内容,并且如果可能,当单词something之前可能或可能没有空格时会发生什么,例如:
  • something(try_(this(once))) 或者
  • something (try_(this(once)))

为什么你不能就这样做呢?https://regex101.com/r/jW9iW0/1 - lintmouse
@dustmouse 对于 something(try_(this(once))), 它同样有效,但是 something (try_(this(once))) 返回空值。如果有任何想法可以匹配可能出现或不出现的空格,请将其作为答案发布,以便我可以给您一些信用。 - Pieter Goosen
好的,我发布了一个可以处理空格的答案。 - lintmouse
3个回答

3

很好,它适用于 something(try_(this(once))),但是 something (try_(this(once))) 没有返回任何内容。有什么想法可以匹配空格,以防万一出现了空格? - Pieter Goosen

3
(?R) 不是一个可以处理平衡的内容(例如圆括号)的神奇口令。 (?R)(?0) 相同,它是“捕获组零”的别名,换句话说,是整个模式。
同样地,您可以使用(?1)(?2)等作为组1、2等中的子模式的别名。
值得一提的是,除了(?0)(?R)显然总在其子模式中,因为它是整个模式,(?1)(?2)只有在它们各自的组中才会引起递归,并且只能用于不重写模式的部分。 something\((?:[^()]|(?R))*\)无法工作,因为它强制每个嵌套的(或非嵌套的)开放括号在您的字符串中都需要有something之前。
结论是,您不能在此处使用(?R),需要创建一个捕获组来处理嵌套的括号:
(\((?:[^()]|(?1))*\))

可以更加高效地编写的代码:

(\([^()]*(?:(?1)[^()]*)*+\))

要完成任务,您只需要添加 something 到递归中,它不再包含在递归中:
something(\([^()]*(?:(?1)[^()]*)*+\))

请注意,如果 something 是一个具有未确定数量的捕获组的子模式,则最好使用相对引用来引用最后打开的捕获组,如下所示:
som(eth)ing(\([^()]*(?:(?-1)[^()]*)*+\))

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接