2016-03-08 63 views
1

我希望能夠將/ proc/drbd的內容解析爲數組以便使用數據。我相信這樣做有一些捷徑或技巧,但是對於我的生活來說,它無法實現!使用PHP解析/ 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)? 

在內部正則表達式的結尾顯然不會提前工作:(

謝謝!

+0

SO問題是您到目前爲止所嘗試的嗎? –

+0

正如問題所述,到目前爲止,我嘗試過的大部分工作都是在一年半左右偶爾看到這個問題,並得出結論,我真的不知道如何最好地解決這個問題,並轉向其他方面。 我能想到的唯一辦法就是做一些非常笨拙的爆炸,這似乎並不值得嘗試投入代碼。 – adama

+0

@adama,你有沒有試圖達到預期的輸出「長」正則表達式? – RomanPerekhrest

回答

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); 
?> 
+0

那麼,這是一大堆神話般的巫術,但它看起來像一個不錯的出發點!謝謝! – adama

+0

@adama:看看更新後的答案,邏輯和正則表達式稍有改變,以便讓所有設備數據匹配。看看ideone演示,看看它的工作。 – Jan

+0

對此進行了一些修改,我解決了這個問題。謝謝! :) – adama