使用PHP将内容解析/ proc / drbd内容转换为数组

时间:2016-03-08 11:25:33

标签: php arrays regex parsing

我希望能够将/ proc / drbd的内容解析成数组以便使用数据。我确信有一些捷径或技巧可以做到这一点,但对于我的生活,它是我的目标!

我认为这是一些复杂的正则表达式的工作?

要解析的文本是:

version: 8.4.3 (api:1/proto:86-101)
srcversion: 6551AD2C98F533733BE558C

 1: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r-----
    ns:1055689 nr:0 dw:7181 dr:1050351 al:6 bm:64 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0
 2: cs:Connected ro:Secondary/Primary ds:UpToDate/UpToDate C r-----
    ns:0 nr:1048508 dw:1048508 dr:0 al:0 bm:64 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0

数组可能如下所示:

{
   'version' -> '8.4.3',
   'api'     -> '1',
   'proto'   -> '86-101',
   'srcversion' -> '6551AD2C98F533733BE558C',
   'devices' -> array { '1' -> array { 'cs' -> 'Connected', 'ro' -> 'Primary/Secondary', ... , 'oos' -> 0 },
                        '2' -> array { 'cs' -> 'Connected', 'ro' -> 'Secondary/Primary', ... , 'oos' -> 0 } }
}

我没有任何我为此尝试的东西的例子,因为我甚至不确定从哪里开始。通常我会用一堆爆炸或preg_match来做这件事,但我很确定这不是正确的解决方案,而且我不确定如何处理分布在两条线上的一个实体的数据!

编辑:

设备重建期间设备数据格式还有另一种变体:

 3: cs:SyncTarget ro:Secondary/Primary ds:Inconsistent/UpToDate C r----
    ns:0 nr:284320 dw:284320 dr:0 al:0 bm:17 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b oos:764188
        [====>...............] sync'ed: 27.4% (764188/1048508)K
        finish: 0:15:55 speed: 416 (320) K/sec

我无法弄清楚如何忽略这些可选的第二行。

            ((\.+)\R)?
            ((\.+)\R)?

内部正则表达式的结尾显然不起作用:(

提前致谢!

1 个答案:

答案 0 :(得分:1)

您可以使用正则表达式和编程逻辑的组合,请参阅a demo on ideone.com 该方法对versionapiprotosrcversion使用外部正则表达式,并为devices使用内部正则表达式。除了实际的正则表达式(在多行和详细模式下),线索是使用PREG_SET_ORDER和命名的捕获组,因此可以在之后循环匹配。内部部分包括分割线和匹配的键/值对:

<?php

$string = <<<EOS
version: 8.4.3 (api:1/proto:86-101)
srcversion: 6551AD2C98F533733BE558C

 1: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r-----
    ns:1055689 nr:0 dw:7181 dr:1050351 al:6 bm:64 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0
 2: cs:Connected ro:Secondary/Primary ds:UpToDate/UpToDate C r-----
    ns:0 nr:1048508 dw:1048508 dr:0 al:0 bm:64 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0
 3: cs:SyncTarget ro:Secondary/Primary ds:Inconsistent/UpToDate C r----
    ns:0 nr:284320 dw:284320 dr:0 al:0 bm:17 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b oos:764188
        [====>...............] sync\'ed: 27.4% (764188/1048508)K
        finish: 0:15:55 speed: 416 (320) K/sec
EOS;


$outerregex = '~
                ^version:\s
                (?P<version>[\d.]+)\s
                \(
                    api:(?P<api>\d+).+?
                    proto:(?P<proto>[-\d]+)
                \)\R
                srcversion:\s(?P<srcversion>.+)\R{2}
                (?P<devices>(?:\s\d(?:.+\R){2})+)
              ~xm';

$outerkeys = array("version", "api", "proto", "srcversion");

$output = array();
preg_match_all($outerregex, $string, $matches, PREG_SET_ORDER);

foreach ($matches as $match) {
    $arr = array();
    // save the outer key/value pairs
    foreach ($outerkeys as $key) $arr[$key] = $match[$key];

    $arr["devices"] = array();

    // split the device to have separate lines
    $lines = preg_split('~\R\s+\d:~', $match["devices"]);

    // loop over these lines
    foreach ($lines as $line) {
        $tmp = array();
        preg_match_all('~(?P<key>\w+):(?P<value>\S+)~', $line, $linematches, PREG_SET_ORDER);
        foreach ($linematches as $linematch)
            $tmp[$linematch["key"]] = $linematch["value"];
        $arr["devices"][] = $tmp;
    }

    $output[] = $arr;
}

print_r($output);
?>