Regex以匹配多维字符串中的顶级分隔符


Regex to match top level delimiters in a multi dimensional string

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

数据看起来像这样:

alpha {
    beta {
        charlie;
    }
    delta;
}
echo;
foxtrot {
    golf;
    hotel;
}

我试图构建的regex(对于preg_match_all)应该与每个顶级父级匹配(由{}个大括号分隔),这样我就可以在匹配中递归,构建一个表示数据的多维php数组。

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

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

匹配1:

    beta {
        charlie;
    }
    delta;
}
echo;
foxtrot {
    golf;
    hotel;

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

    beta {
        charlie;
    }
    delta;

匹配2:

    golf;
    hotel;

那么regex向导,我这里缺少什么功能,或者我需要用php来解决这个问题?任何提示都非常欢迎:)

不能用正则表达式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不要

当然可以用正则表达式实现这一点。

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-deep级别的支架。

我认为您可能会通过匹配[a-zA-Z0-9][:blank]+{}来使用preg_split。您将能够通过遍历结果来构造您的数组。使用一个递归函数,当您匹配一个开始标记时,该函数会更深入,而在一个结束标记时,它会更上层。

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