Reputation: 7784
I would like to find a proper regexp / recursive algorithm to extract data from a string with brackets.
$input = "0A,0B(1A((3A, 3B, 3C)))";
Expected result:
[
0 => ["0A", "0B"],
1 => ["1A"],
2 => [],
3 => ["3A", "3B", "3C"]
];
The following function is pretty close, however, it does not detect empty data when there are nested brackets, so the array has size of 3
instead of 4
:
function extractParameters($line, &$params, $level = 0){
$pattern = "/([A-Za-z0-9,:]+)(?:\((.+)?\))?/" ;
$matches = [] ;
preg_match($pattern, $line, $matches);
//We have a valid value
if (isset($matches[1])){
$set = $matches[1] ;
$params[$level] = explode(",", $set);
//It has some content
if (isset($matches[2])){
$content = $matches[2] ;
extractParameters($content, $params, ++$level);
}
}
}
$input = "0A,0B(1A((3A,3B,3C)))" ;
$params = [];
extractParameters($input, $params);
var_dump($params);
Upvotes: 1
Views: 148
Reputation: 1596
Going by your example, if you change the pattern line to...
$pattern = "/([A-Za-z0-9,:]*)(?:\((.+)?\))?/" ;
...I think it works as you requested.
I switched the plus (+
) sign, which makes the pattern require at least one alphanumeric/comma/semicolon character before the parentheses to an asterix (*
), so it still matches but is not required.
Upvotes: 2
Reputation: 627600
Here is a possible solution:
$re = '/(?<=\(|^)([^()]*)/';
$str = "0A,0B(1A((3A, 3B, 3C)))";
preg_match_all($re, $str, $matches);
$res = array();
foreach ($matches[1] as $m){
$res[] = preg_split('/\s*,\s*/',$m);
}
print_r($res);
See IDEONE demo
The regex (?<=\(|^)([^()]*)
matches 0 or more characters other than (
or )
if preceded with (
or start of string.
Upvotes: 3