0

I have a plain text file with tabbed information inside which looks as follows

ADVMONITOR "WINOSSPI-RPCService-Win2k"
DESCRIPTION "Checks the 'Remote Procedure Call (RPC)' Windows 2000 service and its corresponding process"
INTERVAL "5m2s"
SCRIPTTYPE "VBScript"
MULTISOURCE
INSTANCEMODE  ONCE
MAXTHRESHOLD
SEPARATORS "    "
ICASE
PROGRAM "Process"
    DESCRIPTION "Returns the number of running 'svchost.exe' processes;"
    MONPROG "opcntprocs.exe WINOSSPI-RPCService-Win2k-Process svchost"
PROGRAM "Service"
    DESCRIPTION "Returns  values that correspond to different states of the service 'RPC Service'"
    MONPROG "opcntservice_chk.bat RpcSs WINOSSPI-RPCService-Win2k-Service"
MSGCONDITIONS
    INSTANCERULE "Combined Service and Process Monitor; suppress messages caused by same case;"
    ID "d5ca6823-37d4-4581-886a-2aad3462d9e0"
    DESCRIPTION "Checks the services and processes"
    CONDITION_ID "0cdb88dd-0338-47d3-a5f5-e4d982e8a1a9"
    CONDITION

And what I need is to get the information from each different block on a way that I can import such information into a db, but I cannot get a nice iteration through the different blocks to get the right data from each block on a nice and identifiable manner.

I tried identify the blocks as per the tabs using a class named tabbedLinesTree, this converts all tabbed text into XML, which is useful as well, but the different fields aren't showed with fields name or any other way to identify which block are we going through.

Resuming... I'd like to go thru that file and get (as an example) for each PROGRAM block an array with the PROGRAM name, the DESCRIPTION and the MONPROG for that block...

Not sure how to conceptualize this, can you please help me out on this with any idea?

I'm good at PHP, but can implement any other solution if needed.

Ps: some blocks can have more tabs or more fields (lines) of information.

--- BELOW TEXT ADDED AFTER NIGEL'S ANSWER ---

Second text example...

SYNTAX_VERSION 5

LOGFILE "OvSvcDiscErrorLog"
DESCRIPTION "Self-Management OvService Discovery agent error log"
LOGPATH "<OvSvcDiscErrorLog>"
INTERVAL "5m"
CHSET ASCII
FROM_LAST_POS
NO_LOGFILE_MSG
CLOSE_AFTER_READ
SEPARATORS "    "
MSGCONDITIONS
                DESCRIPTION "[E01-001] EXCEPTION while installing policy"
                SUPP_DUPL_IDENT "3m"
                    COUNTER_THRESHOLD 0
                CONDITION_ID "17adc1d1-32cf-42ca-be5f-1cf784f19026"
                CONDITION
                    TEXT "<*> \\[E01-001\\] EXCEPTION while installing policy <*.polname>" SEPARATORS "     "
                SET
                    SEVERITY Critical
                    APPLICATION "OVO/Win"
                    MSGGRP "OVO"
                    OBJECT "OvSvcDiscAgent"
                    TEXT "[E01-001]EXCEPTION while installing policy "`
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Emiliano
  • 83
  • 6
  • can you indicate the tabs in the input file format? – herrjeh42 Apr 30 '13 at 20:26
  • Hi Emiliano, that second example looks like it has a tree-like structure. Eg. `SET` is a child of `MSGCONDITIONS`, and `SEVERITY` and `APPLICATION` are children of `SET`. Does that seem correct? – Nigel Alderton May 02 '13 at 22:43
  • hey guys! sorry, didn't saw your last comments... Jamie, thanks for your answer, what you mean with indicate? want me to highlight the tabs? I can do that. Nigel, exactly that! :) – Emiliano May 08 '13 at 13:31
  • Write simple parser https://github.com/rjhdby/HpomMetricsParser – rjhdby Jul 18 '17 at 12:36

1 Answers1

0

Hi this isn't pretty but it works. The final result produced by the code below looks like this;

Array
(
    [PROGRAM_Process] => Array
        (
            [name] => Process
            [DESCRIPTION] => Returns the number of running 'svchost.exe' processes;
            [MONPROG] => opcntprocs.exe WINOSSPI-RPCService-Win2k-Process svchost
        )

    [PROGRAM_Service] => Array
        (
            [name] => Service
            [DESCRIPTION] => Returns  values that correspond to different states of the service 'RPC Service'
            [MONPROG] => opcntservice_chk.bat RpcSs WINOSSPI-RPCService-Win2k-Service
        )

)

At it's heart is the PHP parse_ini_file() function. parse_ini_file() takes as its input a text file in the normal .ini format eg;

[first_section]
one = 1
five = 5
animal = BIRD

[second_section]
path = "/usr/local/bin"
URL = "http://www.example.com/~username"

and returns an associative array. Most of the code below is concerned with reforming your input file to make it suitable for parse_ini_file(). The reforming is done by the foreach loop. The reformed data is assembled in the array $arr_ini.

Unfortunately parse_ini_file() will only take as its input a file (not a string) so I've had to use a temporary file called tmp.ini.

<?php

$tmp_file = 'tmp.ini';
$input_file = 'input.txt';
$arr_input = explode("\r\n", file_get_contents($input_file));
$arr_ini = array();
$flg_collate = false;

foreach($arr_input as $line) {

  $split = explode(' ', trim($line), 2);

  if ($flg_collate) {
    if (substr($line, 0, 1) == ' ') {
      $arr_ini[] = $split[0].'='.$split[1];
    } else {
      $flg_collate = false;
    }
  }

  if ($split[0] == 'PROGRAM') {
    $without_quotes = trim($split[1], '"');
    $arr_ini[] = "[PROGRAM_$without_quotes]";
    $arr_ini[] = "name = {$split[1]}";
    $flg_collate = true;
  }
}

file_put_contents($tmp_file, implode("\r\n", $arr_ini));
$arr_result = parse_ini_file($tmp_file, true);

echo "<h1>Reformed array</h1><xmp>".print_r($arr_ini, true)."</xmp>";
echo "<h1>Result as an Array</h1><xmp>".print_r($arr_result, true)."</xmp>";

?>

The result is $arr_result. The first echo outputs one of the intermediate steps. The second echo outputs the result.

Hope that helps.

Nigel Alderton
  • 2,265
  • 2
  • 24
  • 55
  • Hi @Nigel! thank you for your answer. I found two things here that make me believe it wont work. First not all the blocks I need to identify starts with "PROGRAM" and second some blocks can have different tabs at the beginning of the line (sometimes one or two, other times three, four, five or more) See the new example of how the source change. – Emiliano May 02 '13 at 14:23
  • You added the second example to your question the day after you posted your original question. When you ask a question then change it later, the common practice is to make it clear that you have changed the question, usually by adding the word **Edit** or similar. That way there is no chance of making people who answer your original question look foolish. – Nigel Alderton May 02 '13 at 18:36
  • Sorry @Nigel, it was not my intention you feel foolish, actually.. I don't think you look that way as you provided me with the first answer showing me you are willing to help and also it was a good answer but didn't covered all I needed. Sorry if I wasn't clear enought so I needed to add new code I've added to the question to show how the possible variants can look like but please go thru my original post and see the PS, it clearly says that "some blocks can have more tabs". – Emiliano May 02 '13 at 19:50
  • Thank you again for your answer and if you don't want to write me anymore as per this confusion I will understand, but again... it was my first question ever, I don't know all the rules and it wasn't my intention to do what you said... ah... an the only edit I did was ADD the second example, I didn't changed anything and commented only on your reply to provide more details. Thank you again! – Emiliano May 02 '13 at 19:50
  • Sorry I didn't mean to sound like I was admonishing you. It's no biggie, just a small point of etiquette. But thank you for re-editing your question as per my suggestion. I appreciate that :) – Nigel Alderton May 02 '13 at 22:22