在潜在嵌套时获取两个分隔符之间的匹配

时间:2018-01-23 17:16:35

标签: php regex preg-match pcre

我的案例的具体分隔符是左右括号。如果没有嵌套,我可以按如下方式在它们之间获取文本:

$input = 'sometext(moretext)andmoretext(somemoretext)andevenmoretext(andmore)';
preg_match_all('#\((.*?)\)#', $input, $match);
echo('<pre>'.print_r($match[1],1).'</pre>');

Array
(
    [0] => moretext
    [1] => somemoretext
    [2] => andmore
)

然而,当我有嵌套字符时,我遇到了一些障碍,并得到以下内容。

$input = 'sometext(moretext)andmoretext(somemore(with(bitof(littletext)text)more(andmore)text)text)andevenmoretext(andmore)';
preg_match_all('#\((.*?)\)#', $input, $match);
echo('<pre>'.print_r($match[1],1).'</pre>');

Array
(
    [0] => moretext
    [1] => somemore(with(bitof(littletext
    [2] => andmore
    [3] => andmore
)

如何在分隔符之间返回整个字符串:

Array
(
    [0] => moretext
    [1] => somemore(with(bitof(littletext)text)more(andmore)text)text
    [2] => andmore
)

PS。最后,我将使用递归PHP在任何包含括号的顶级匹配上执行相同的任务。

2 个答案:

答案 0 :(得分:1)

您可以使用此recursive regex pattern来匹配匹配的(...)

preg_match_all('/\( ( (?: [^()]* | (?R) )* ) \)/x', $input, $m);
print_r($m[1]);

RegEx Demo

(?R)递归整个模式。

<强>输出:

Array
(
    [0] => moretext
    [1] => somemore(with(bitof(littletext)text)more(andmore)text)text
    [2] => andmore
)

答案 1 :(得分:0)

为了做到这一点,这里是一个非正则表达式解决方案。

function delimeterSplit( $input )
{
    $str = '';
    $output = array();

    $op = 0;
    $cp = 0;

    foreach( str_split( $input ) as $k => $v )
    {
        if( $v === '(' )
        {
            ++$op;
        }
        if( $input[ $k ] === ')' )
        {
            ++$cp;
        }
        if( ( ( $op === 1 && $v !== '(' ) || $op > 1 ) && $op !== $cp )
        {
            $str .= $v;
        }
        if( $op > 0 && $op === $cp )
        {
            $op = 0;
            $cp = 0;
            $output[] = $str;
            $str = '';
        }
    }

    return $output;
}

echo '<pre>'.print_r( delimeterSplit( 'sometext(moretext)andmoretext(somemoretext)andevenmoretext(andmore)' ), true ).'</pre>';

echo '<pre>'.print_r( delimeterSplit( 'sometext(moretext)andmoretext(somemore(with(bitof(littletext)text)more(andmore)text)text)andevenmoretext(andmore)' ), true ).'</pre>';

输出:

Array
(
    [0] => moretext
    [1] => somemoretext
    [2] => andmore
)

Array
(
    [0] => moretext
    [1] => somemore(with(bitof(littletext)text)more(andmore)text)text
    [2] => andmore
)