Intereting Posts

Содержимое верхнего уровня regex из строки

Пожалуйста, помогите, мои навыки регулярного выражения не дают мне возможности. У меня есть следующая строка:

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

Я хочу иметь возможность извлекать любые данные между квадратными скобками, но не там, где эти данные являются подмножеством уже выделенного набора. Поэтому любые вложения должны быть оставлены как часть извлеченной строки родителя.

В приведенном выше примере я бы извлек две части:

 "number" "title|addresses[id]" 

Обратите внимание на то, как [id] не извлекается, поскольку он является частью набора данных более низкого уровня.

Я пытаюсь сделать это с помощью preg_match, но думаю, что мне, возможно, придется прибегать к повторению каждого символа в строке.

Вот регулярное выражение:

 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]; 

Печальная истина заключается в том, что регулярное выражение не может обрабатывать скобки, потому что регулярное выражение не имеет памяти. (Это эквивалентно DFA )

Чтобы добиться того, чего вы хотите, вам придется написать небольшой парсер самостоятельно (я думаю), использование стека может решить проблему;)

Основная идея, использующая стек для решения проблемы, заключается в том, что … каждый раз, когда вы видите [вы нажимаете стек, и каждый раз, когда вы видите], вы поместите стек и отпустите строку, которую вы получили с тех пор, как вы видели последний раз ,

Надеюсь это поможет 😉

Я написал небольшой парсер для достижения желаемых результатов:

Код:

 $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; } 

Вывод:

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

Демо-версия