获取所有嵌套的花括号

Posted

技术标签:

【中文标题】获取所有嵌套的花括号【英文标题】:Get all nested curly braces 【发布时间】:2013-04-21 21:48:57 【问题描述】:

可以从字符串中获取嵌套花括号中的所有内容吗?例如:

敏捷棕色狐狸跳过懒惰狗

所以我需要:

快速 结束 跳过懒惰

在这个序列中更好,从最嵌套的开始。

【问题讨论】:

构建一个简单的解析器或尝试使用递归正则表达式。 php 文档中有一条评论可能会引导您找到所需的内容:us3.php.net/manual/en/regexp.reference.recursive.php#102748 【参考方案1】:

解决方案

下面的正则表达式将允许您获取所有嵌套花括号的内容。请注意,这假设嵌套的花括号是平衡的;否则,很难定义答案应该是什么。

(?=\((?:[^]++|\(?1)\)++)\)

结果将在捕获组 1 中。

DEMO

请注意,该顺序与问题中指定的顺序不同。打印出的顺序是由左大括号的出现顺序定义的,也就是说最外面的对的内容会先打印出来。

说明

暂时忽略零宽度正向预测 (?=pattern),让我们关注里面的模式,即:

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

两个大括号之间的部分 - ((?:[^]++|\(?1)\)++) 将匹配 1 个或更多 个实例:

非空非花括号字符序列[^]++,或 递归匹配 包围的块,其中可能包含许多其他非花括号序列或其他块。

上面的模式单独可以匹配不包含的文本,我们不需要。因此,我们确保匹配是一个由 括起来的块,由一对花括号 在两端:\((?:[^]++|\(?1)\)++)\

由于我们希望所有嵌套花括号内的内容,我们需要防止引擎消费文本。这就是 零宽度正向预测 发挥作用的地方。

这不是很有效,因为您将重做嵌套括号的匹配,但我怀疑是否有任何其他通用解决方案使用正则表达式可以有效地处理它。

普通代码可以一次有效地处理所有事情,如果您将来要扩展您的需求,建议使用。

【讨论】:

【参考方案2】:

一次性使用正则表达式的简单解决方案:

$str = 'The quick brown fox jumps over the lazy dog';

$result = parseCurlyBrace($str);

echo '<pre>' . print_r($result,true) . '</pre>';

function parseCurlyBrace($str) 

  $length = strlen($str);
  $stack  = array();
  $result = array();

  for($i=0; $i < $length; $i++) 

     if($str[$i] == '') 
        $stack[] = $i;
     

     if($str[$i] == '') 
        $open = array_pop($stack);
        $result[] = substr($str,$open+1, $i-$open-1);
     
  

  return $result;

【讨论】:

比您删除的解决方案好得多。 +1 谢谢你,考虑到以前的恐惧,我睡不好:-)【参考方案3】:

你可以试试这个:

$subject = 'The quick brown fox jumps over the lazy dog';

function nestor($subject) 
    $result = false;    
    preg_match_all('~[^]+|\(?<nested>(?R)*)\~', $subject, $matches);

    foreach($matches['nested'] as $match) 
        if ($match != "") 
            $result[] = $match;
            $nesty = nestor($match);
            if ($nesty) 
                $result = array_merge($result,$nesty); 
                // $result[]=$nesty; // to preserve the hierarchy
        
    
    return $result;


print_r(nestor($subject));

此处使用的模式匹配嵌套结构,但无法以大于 1 的深度捕获。 这就是为什么嵌套函数递归地应用于每个匹配的原因。

您可以使用 \G 功能探索另一种模式:

$subject = 'The quick brown fox jumps over the fat lazy dog';
$pattern = '~[^]++|\G\(?<nested>(?R)*+)\~';
preg_match_all($pattern, $subject, $matches/*, PREG_SET_ORDER*/);
print_r($matches);

如果查看结果,您可以轻松确定规则以了解每个元素的级别深度。

【讨论】:

完美。谢谢sn-p兄弟。【参考方案4】:

你可以用一种 hacky、丑陋的方式来做,如下所示:

1) 搜索正则表达式([^]*)的所有匹配项

2) 搜索正则表达式([^]*[^]*[^]*)的所有匹配项(如您所见,这是可以动态构造的)

3) 搜索正则表达式 ([^]*[^]*[^]*[^]*[^]*)... 的所有匹配项(不断动态构造它,直到找不到匹配项)

捕获组,由 ()s 表示,就在 s 的外部对内,将允许您仅捕获第一个捕获组中的内容,而不是整个正则表达式匹配。

【讨论】:

以上是关于获取所有嵌套的花括号的主要内容,如果未能解决你的问题,请参考以下文章

App.post 返回空的花括号集

使用 Kotlin 的 RxJava 中的花括号和普通括号有啥区别

Java中的花括号本身是啥意思?

函数的 JavaScript 参数中的花括号

Scala方法调用中的花括号[重复]

关于if语句后面的花括号