当前位置: 首页 > 知识库问答 >
问题:

用php正则表达式解析嵌套的大括号

程正阳
2023-03-14

我想将带有嵌套大括号的原始字符串解析为多维数组。下面我添加了一些有效的示例代码。但主要问题是,我的正则表达式只捕获第一个匹配的组,而忽略了另一个发生。

非常感谢您的帮助。

代码:

$regex = '/(?ims)(group [a-z0-9\s\,\.\:#_\-@]+)\{([^\}]*)\}/';
preg_match_all( $regex, file_get_contents('data.txt', FILE_USE_INCLUDE_PATH), $arr); 
    $result = array();
    foreach ($arr[0] as $i => $x)
    {
        $selector = trim($arr[1][$i]);
        $rules = explode(';', trim($arr[2][$i]));
        $result[$selector] = array();
        foreach ($rules as $strRule)
        {
            if (!empty($strRule))
            {
                $rule = explode(" = ", $strRule);
                $result[$selector][][trim($rule[0])] = trim($rule[1]);
            }
        }
    }

原始字符串(data.txt):

group A { T1 { X = 44; }
          T2 { Y = 33; } }

group B { T1 { X = 555; } }

代码输出:

Array (
    [group A] => Array ( 
        [0] => Array ( 
            [T1 { X] => 44 
        ) 
    )
    [group B] => Array ( 
        [0] => Array ( 
            [T1 { X] => 555 
        ) 
    )
)

但例外输出:

Array(
    [group A] => Array(
        [T1] => Array(
            [X] => 44
        ) 
        [T2] => Array (
            [Y] => 33
        )
    )
    [group B] => Array(
        [T1] => Array(
            [X] => 555
        )
    )
)

共有1个答案

孟成化
2023-03-14

可能存在更好的解决方案,但它是有效的。

确保您的输入不能有更深的值,否则您必须改进/重写entiere规则!

$input = <<<REG
group A { T1 { X = 44; }
          T2 { Y = 33; } }

group B { T1 { X = 555; } }
REG;

$out   = [];
$cbuff = null;
$rule  = "/^(?<group>[^\{\}]*)?\{|((?<set>[\w\s]+)\{(?<var>[\w\s]+)=(?<val>[\d\s]+)[;\s]+\})/im";
preg_replace_callback($rule, function($m)
use(&$out, &$cbuff) // import locally our working requirements
{
    $m = array_filter($m, "is_string", ARRAY_FILTER_USE_KEY); // cleaning
    $m = array_map("trim", array_filter($m)); // cleaning and trim

    if(key($m)=="group") // get & create the current root group
        $out[($cbuff = reset($m))] = [];

    if(isset($m["var"])) // assuming 'var' exists, you'll get 'set/var' too
    {
        if(is_null($cbuff)) return; // prevent no group found
        $out[$cbuff][$m["set"]] = [$m["var"] => $m["val"]];
    }
}, $input);

var_dump($out);

将输出:

array(2) {
  ["group A"]=>
  array(2) {
    ["T1"]=>
    array(1) {
      ["X"]=>
      string(2) "44"
    }
    ["T2"]=>
    array(1) {
      ["Y"]=>
      string(2) "33"
    }
  }
  ["group B"]=>
  array(1) {
    ["T1"]=>
    array(1) {
      ["X"]=>
      string(3) "555"
    }
  }
}

我认为你对PHP没问题,但我对正则表达式做了一些解释:

首先,我为每个部件的set/var/val模式使用了命名组:

在匹配输出下授予自己的组密钥

(?

最后,为了将子属性与根组分开,我只需要匹配任何不包含方括号的部分

你可以在regex101上取回我的板凳

3 matches, 60 steps (~0ms)
5 matches, 107 steps (~0ms)

是的,它可以优化!

 类似资料:
  • 问题内容: 我一直试图在Java中编写一个正则表达式以删除下面括号中的所有内容,同时保留其他所有内容。 注意,括号可以嵌套,这就是为什么我的模式失败的原因 。有人能帮我吗?下面我试过了: 但这打印: d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 OO 6. Be2 e5 7. dxe5 dxe5 8. Qxd8 Rxd8 9. Bg5 Nbd7 10. OO

  • 正如标题所说,以下是一个输入示例: 当然,匹配的字符串将通过递归进行处理。 我希望第一个递归匹配: 之后的过程不用说。。。

  • 问题内容: 是否有单个正则表达式可以解析表示简单布尔运算的字符串(在Python和/或Javascript中,不必是同一表达式)?例如我想解析这个字符串: 假定: 括号不嵌套 术语a,b,…,z不是子表达式 生成的捕获应首先按括号分组,然后再使用相同或更简单的正则表达式对其进行解析。 我已经成功地编写了一个天真的正则表达式来解析不带括号的布尔运算。 有任何想法吗? 问题答案: 通常,您将使用递归下

  • 我有这样一个文本: 我试图在c#中使用正则表达式来提取嵌套的if/eles-段。 要查找“?”,我使用了: 模式1: 找到“:”我用了: 模式2:

  • 我有一个输入字符串,里面有括号,外面有双引号。这些括号可以嵌套。我想去掉只有在双引号外才有括号的字符串。 我尝试了这个正则表达式这将获取包含在圆括号内的所有内容,无论双引号内外。 我得到的实际输出是: 我预计产出为:

  • 问题内容: 我正在尝试匹配带有嵌套括号的类似数学表达式的字符串。 [‘((((1 + 0)+1)+1)’] 我希望它与所有包含的表达式匹配,例如(1 + 0),((1 + 0)+1)… 我什至不在乎它是否匹配不需要的表达式,例如(((1 + 0),我可以照顾的。 为什么它还没有这样做,我该怎么做? 问题答案: 正则表达式尝试匹配尽可能多的文本,从而消耗了所有字符串。它不会在字符串的一部分上寻找正则