Looking for an answer either in pseudo or workable in PHP if you're feeling generous.
Currently I have a file with the following syntax:
ITEM 1
Pet Dog
Origin Earth
BEGIN Square
ITEM 2
BEGIN "0 0" Type "Earth over" Temp 0.1 END
BEGIN "0 1" Type "Earth over" Temp 0.1 END
BEGIN "0 2" Earth 0.1827 END
END
BEGIN "0100"
ITEM 2
Origin Earth
BEGIN Alpha
ID 1
Name Alpha
END
BEGIN "Need"
BEGIN "00" id.a END
BEGIN "01" id.b END
END
END
I wish to be able to take this and parse this into a usable array similar to this:
array(
"ITEM" => "1",
"Pet" => "Dog",
"Origin" => "Earth",
"Square" => array(
"ITEM" => "2",
"0 0" => array(
"Type" => "Earth over",
"Temp" => "0.1"
),
"0 1" => array(
"Type" => "Earth over",
"Temp" => "0.1"
),
"0 2" => array(
"Earth" => "0.1827"
),
),
"0100" => array(
"ITEM" => "2",
"Origin" => "Earth",
"Alpha" => array(
"ID" => "1",
"Name" => "Alpha"
),
"Need" => array(
"00" => "id.a",
"01" => "id.b"
)
)
)
Note that I'm not worried about value types - strings are perfectly fine for what I'm doing.
This is a function that parses that text. It may need adjustments and additions if the format is more complex than is exposed in the question. It also needs some error handling when the input data does not match the expected format.
/**
* Parse the provided lines of text into an array.
* Warning: it modifies the input parameter. At the end of the execution, $lines will be empty.
*/
function parseData(array &$lines)
{
$result = array(); // this is where the current block is stored
// Process one line at a time...
do {
$l = trim(array_shift($lines)); // extract the first line into $l (and remove it from $lines)
$p = str_getcsv($l, ' ', '"'); // split $l into words (take care of strings eclosed in quotes)
$key = array_shift($p); // get the first word from the line
switch ($key)
{
default: // simple "key value" lines
$result[$key] = implode(' ', $p); // combine the remaining words from $p into a single string
break;
case 'BEGIN': // start a new block
$key = array_shift($p); // the real key in the array follows the 'BEGIN' keyword
if (end($p) == 'END') { // check if the entire block is on a single line
array_pop($p); // remove 'END' from the end of the array
if (count($p) == 1) { // only one word remaining in $p:
$result[$key] = array_shift($p); // it is the value
} else { // more than one word in $p: this is a list of properties
$aa = array(); // put the values of this one-line block here
while (count($p) > 1) {
$k = array_shift($p); // they come in pairs: key followed by value
$v = array_shift($p);
$aa[$k] = $v;
}
$result[$key] = $aa; // the entire line was parsed; store it
}
} else { // the last word on the line is not 'END'
$result[$key] = parseData($lines); // recursively call this function to parse the inner block and store its result
} // it will return after it consumes the line that starts with 'END'
break;
case 'END': // here ends the block
return $result; // return the collected values
}
} while (count($lines)); // ... until there are no more lines to process
return $result; // no more lines to process; return the collected data
}
How to use it:
$text = file_get_contents('1.txt');
$lines = explode("
", trim($text));
$data = parseData($lines);
print_r($data);