Reputation: 23
I'm trying to build a recursive function in PHP that takes a string with nested {} values and converts it into an nested array. Is there any built in functions that can simply split this?
Also the { brackets will always be on the same line as the key i.e. (Main{) not Main\n{.
Indentation will also always be consistent.
Example of what I'm looking for below.
Main{
NetworkAccess 1;
MaxCPE 6;
MaxClassifiers 20;
GlobalPrivacyEnable 1;
BaselinePrivacy{
AuthTimeout 10;
ReAuthTimeout 10;
AuthGraceTime 600;
OperTimeout 10;
ReKeyTimeout 10;
TEKGraceTime 600;
AuthRejectTimeout 60;
SAMapWaitTimeout 1;
SAMapMaxRetries 4;
}
UsServiceFlow{
UsServiceFlowRef 1;
QosParamSetType 7;
TrafficPriority 2;
MaxRateSustained 1000000;
SchedulingType 2;
MaxTrafficBurst 8000;
MaxConcatenatedBurst 8000;
}
DsServiceFlow{
DsServiceFlowRef 101;
QosParamSetType 7;
TrafficPriority 2;
MaxRateSustained 10000000;
}
}
Desired result:
Array
(
[Main] => Array
(
[NetworkAccess] => 1
[MaxCPE] => 6
[MaxClassifiers] => 20
[GlobalPrivacyEnable] => 1
[BaselinePrivacy] => Array
(
[AuthTimeout] => 10
[ReAuthTimeout] => 10
[AuthGraceTime] => 600
[OperTimeout] => 10
[ReKeyTimeout] => 10
[TEKGraceTime] => 600
[AuthRejectTimeout] => 60
[SAMapWaitTimeout] => 1
[SAMapMaxRetries] => 4
)
[UsServiceFlow] => Array
(
[UsServiceFlowRef] => 1
[QosParamSetType] => 7
[TrafficPriority] => 2
[MaxRateSustained] => 1000000
[SchedulingType] => 2
[MaxTrafficBurst] => 8000
[MaxConcatenatedBurst] => 8000
)
[DsServiceFlow] => Array
(
[DsServiceFlowRef] => 101
[QosParamSetType] => 7
[TrafficPriority] => 2
[MaxRateSustained] => 10000000
)
)
)
Upvotes: 1
Views: 138
Reputation: 163362
Another option for your current data and with the consistent curly brackets might be to use a recursive function making use of references keeping track of the current and the parent.
Explode on a newline and pass that array as a starting point. For every iteration take the first one off the top using array_shift which will return null if the array is empty.
If the last character is a {
, the current will be the parent and the set a new array as the current for the next iteration.
When the only character is a }
use the parent for the next iteration.
For example:
function processItems($items, &$current, &$parent) {
$item = trim(array_shift($items));
if ($item) {
if (substr($item, -1) === '{') {
$key = rtrim($item, '{');
$current[$key] = [];
processItems($items, $current[$key], $parent);
return;
}
if (trim($item) === '}') {
processItems($items, $parent, $parent);
return;
}
$parts = explode(' ', $item);
$current[$parts[0]] = rtrim($parts[1], ';');
processItems($items, $current, $parent);
}
}
$curr = [];
processItems(explode("\n", $data), $curr, $curr);
print_r($curr);
Result
Array
(
[Main] => Array
(
[NetworkAccess] => 1
[MaxCPE] => 6
[MaxClassifiers] => 20
[GlobalPrivacyEnable] => 1
[BaselinePrivacy] => Array
(
[AuthTimeout] => 10
[ReAuthTimeout] => 10
[AuthGraceTime] => 600
[OperTimeout] => 10
[ReKeyTimeout] => 10
[TEKGraceTime] => 600
[AuthRejectTimeout] => 60
[SAMapWaitTimeout] => 1
[SAMapMaxRetries] => 4
)
)
[UsServiceFlow] => Array
(
[UsServiceFlowRef] => 1
[QosParamSetType] => 7
[TrafficPriority] => 2
[MaxRateSustained] => 1000000
[SchedulingType] => 2
[MaxTrafficBurst] => 8000
[MaxConcatenatedBurst] => 8000
)
[DsServiceFlow] => Array
(
[DsServiceFlowRef] => 101
[QosParamSetType] => 7
[TrafficPriority] => 2
[MaxRateSustained] => 10000000
)
)
Upvotes: 0
Reputation: 78994
JSON would be better, but it was going to be more difficult as it doesn't like trailing commas where they are not needed (PHP doesn't mind).
$string = "[".str_replace(['{', '}', ';'], ['[', '],', ','], $string)."]";
$string = preg_replace('/([a-z]+)/i', '"$1" =>', $string);
eval("\$result = $string;");
print_r($result);
Upvotes: 2