0

我有一个以大型多维结构构成的文件,类似于 json,但不够接近,无法使用 json 库。

数据看起来像这样:

alpha {
    beta {
        charlie;
    }
    delta;
}

echo;
foxtrot {
    golf;
    hotel;
}

我正在尝试构建的正则表达式(对于 preg_match_all)应该匹配每个顶级父级(由 {} 大括号分隔),以便我可以递归匹配,构建一个表示数据的多维 php 数组。

我尝试的第一个正则表达式是/(?<=\{).*(?=\})/s贪婪地匹配大括号内的内容,但这并不完全正确,因为当顶层有多个同级时,匹配过于贪婪。下面的例子:

使用正则表达式/(?<=\{).*(?=\})/s匹配如下:

第一场比赛:

    beta {
        charlie;
    }
    delta;
}

echo;
foxtrot {
    golf;
    hotel;

相反,结果应该是:匹配 1:

    beta {
        charlie;
    }
    delta;

比赛2:

    golf;
    hotel;

那么正则表达式向导,我在这里缺少什么功能,或者我需要以某种方式用 php 解决这个问题?非常欢迎任何提示:)

4

3 回答 3

2

您不能1使用正则表达式执行此操作。

或者,如果要匹配从深到浅的块,可以使用\{[^\{\}]*?\}andpreg_replace_callback()存储该值,然后返回null以从字符串中擦除它。回调将需要相应地处理嵌套值。

$heirarchalStorage = ...;
do {
    $string = \preg_replace_callback('#\{[^\{\}]*?\}#', function($block)
    use(&$heirarchalStorage) {
        // do your magic with $heirarchalStorage
        // in here
        return null;
    }, $string);
} while (!empty($string));

不完整、未经测试且无保修。

这种方法要求字符串也被包裹起来{},否则最终匹配将不会发生,您将永远循环。

对于可以使用众所周知的交换/存储格式(例如 JSON)轻松解决的问题,这是非常多(低效)的工作。

1我本来打算说“你可以,但是…… ”,但我还是再说一遍,“你不能 2

2不要

于 2012-07-13T09:42:08.527 回答
2

当然你可以用正则表达式来做到这一点。

preg_match_all(
    '/([^\s]+)\s*{((?:[^{}]*|(?R))*)}/',
    $yourStuff,
    $matches,
    PREG_SET_ORDER
);

这在比赛中给了我以下信息:

[1]=>
string(5) "alpha"
[2]=>
string(46) "
beta {
    charlie;
}
delta;
"

[1]=>
string(7) "foxtrot"
[2]=>
string(22) "
golf;
hotel;
"

稍微分解一下。

([^\s]+)                # non-whitespace (block name)
\s*                     # whitespace (between name and block)
{                       # literal brace
    (                   # begin capture
        (?:             # don't create another capture set
            [^{}]*      # everything not a brace
            |(?R)       # OR recurse
        )*              # none or more times
    )                   # end capture
}                       # literal brace

仅供参考,这适用于 n 深级别的大括号​​。

于 2012-07-13T10:12:47.493 回答
0

我想你可能会preg_split通过匹配[a-zA-Z0-9][:blank]+{和得到一些东西}。您将能够通过查看结果来构建您的数组。使用递归函数,当你匹配一个开始标签时,它会更深,而在结束标签上则更高。

否则,最干净的解决方案是实现ANTLR语法!

于 2012-07-13T09:42:59.990 回答