正则表达式匹配多维字符串中的顶级分隔符

时间:2012-07-13 09:26:43

标签: php regex pcre multidimensional-array

我有一个大型多维结构的文件,类似于json,但不足以让我使用json库。

数据看起来像这样:

alpha {
    beta {
        charlie;
    }
    delta;
}

echo;
foxtrot {
    golf;
    hotel;
}

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

我尝试的第一个正则表达式是/(?<=\{).*(?=\})/s,它贪婪地匹配大括号内的内容,但是这不太正确,因为当顶级中有多个兄弟时,匹配太贪婪了。示例如下:

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

匹配1:

    beta {
        charlie;
    }
    delta;
}

echo;
foxtrot {
    golf;
    hotel;

相反,结果应该是: 比赛1:

    beta {
        charlie;
    }
    delta;

比赛2:

    golf;
    hotel;

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

3 个答案:

答案 0 :(得分:2)

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

或者,如果要匹配深度到浅的块,可以使用\{[^\{\}]*?\}preg_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 不要

答案 1 :(得分: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级深层次的支撑。

答案 2 :(得分:0)

我认为您可以通过匹配[a-zA-Z0-9][:blank]+{}来使用preg_split获得一些内容。您将能够通过查看结果来构建数组。使用递归函数,当匹配开始标记时,该函数会更深,而在结束标记上则更高。

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