Top level regex content from string

Please help, my regular expression skills do not give me the opportunity. I have the following line:

username|email_address|phone_numbers[number]profile[title|addresses[id]] 

I want to be able to extract any data between square brackets, but not where this data is a subset of an already selected set. Therefore, any attachments should be left as part of the parent line.

In the above example, I would extract two parts:

 "number" "title|addresses[id]" 

Note that [id] is not retrieved as part of a lower level dataset.

I'm trying to do this with preg_match, but I think that I may have to resort to repeating each character in a string.

+2
source share
3 answers

There is a regex here:

 preg_match_all( '/(?<=\[) # Assert that the previous characters is a [ (?: # Match either... [^[\]]* # any number of characters except brackets | # or \[ # an opening bracket (?R) # containing a match of this very regex \] # followed by a closing bracket )* # Repeat as needed (?=\]) # Assert the next character is a ]/x', $subject, $result, PREG_PATTERN_ORDER); $result = $result[0]; 
+3
source

The sad truth is that the regex cannot handle brackets because the regex has no memory. (This is equivalent to DFA )

To achieve what you want, you have to write a small parser yourself (I think), using the stack can solve the problem;)

The main idea using the stack to solve the problem is that ... every time you see [you push the stack, and every time you see] you will fold the stack and backtrack from the line you got with since [last seen.

Hope this helps;)

+3
source

I wrote a small parser to achieve the desired results:

Code:

 $data = 'username|email_address|phone_numbers[number]profile[title|addresses[id]wut]aaa[another test] aaand another one [which is [more] c[omplexer]t[h[an]] the others]'; print_r(parse($data)); function parse($string, $s1='[', $s2=']'){ $c1 = $c2 = 0;$s = 1; $l = strlen($string); $array = array(array(), array()); for($i=0;$i < $l;$i++){ if($string[$i] == $s1){ $c1++; $array[0][$c1] = $i; }elseif($string[$i] == $s2){ $c2++; $array[1][$c2] = $i; if($c1 == $c2){ $results[] = substr($string, $array[0][$s], $array[1][$c2] - $array[0][$s] + 1); $s=$c1+1; } } } return $results; } 

Output:

 Array ( [0] => [number] [1] => [title|addresses[id]wut] [2] => [another test] [3] => [which is [more] c[omplexer]t[h[an]] the others] ) 

online demo

+1
source

Source: https://habr.com/ru/post/1480225/


All Articles