Intereting Posts
Получить данные из URL-адреса Перенаправление страницы входа / регистрации WordPress на пользовательскую страницу входа / регистрации Нажимаем на каждое поле массива PHP Перенаправить * .htm в * .php Ресурс php mysql_connect всегда одинаковый Игнорирование сообщения об ошибке сервера при использовании Yii CMemCache Неопределенная ошибка смещения, но смещение не определено Как защитить PDF с помощью имени пользователя и пароля? Как синхронизировать ролики YouTube на нескольких клиентах? Предупреждение: openssl_pkcs7_sign (): ошибка получения закрытого ключа с использованием WAMP Передача данных из динамически созданного списка с одной страницы на другую Как я могу обойти отсутствие блока finally в PHP? Что произойдет, когда location.href будет изменен до завершения запроса ajax? php mcrypt – дешифрование и шифрование файлов? Какова наилучшая практика для включения файлов PHP?

Разбор строки с рекурсивными круглыми скобками

Я пытаюсь проанализировать строку со следующей структурой в PHP:

a,b,c(d,e,f(g),h,i(j,k)),l,m,n(o),p 

Например, «настоящая» строка будет:

 id,topic,member(name,email,group(id,name)),message(id,title,body) 

Мой конечный результат должен быть массивом:

 [ id => null, topic => null member => [ name => null, email => null, group => [ id => null, name => null ] ], message => [ id => null, title => null, body => null ] ] 

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

Цель состоит в том, чтобы проанализировать параметр запроса полей для REST API, чтобы позволить клиенту выбирать поля, которые он хочет, из коллекции сложных объектов, и я не хочу ограничивать «глубину» выбора поля.

Как отметил Wiktor, это можно сделать с помощью лексера. Следующий ответ использует класс, первоначально из Никиты Попопва, который можно найти здесь .

Что оно делает

Он просматривает строку и ищет совпадения, как определено в $tokenMap . Они определяются как T_FIELD , T_SEPARATOR , T_OPEN и T_CLOSE . Найденные значения помещаются в массив с именем $structure .
Впоследствии нам нужно перебрать этот массив и построить из него структуру. Поскольку могут быть множественные вложения, я выбрал рекурсивный подход ( generate() ).

демонстрация

Демо можно найти на ideone.com .

Код

Фактический код с пояснениями:

 // this is our $tokenMap $tokenMap = array( '[^,()]+' => T_FIELD, # not comma or parentheses ',' => T_SEPARATOR, # a comma '\(' => T_OPEN, # an opening parenthesis '\)' => T_CLOSE # a closing parenthesis ); // this is your string $string = "id,topic,member(name,email,group(id,name)),message(id,title,body)"; // a recursive function to actually build the structure function generate($arr=array(), $idx=0) { $output = array(); $current = null; for($i=$idx;$i<count($arr);$i++) { list($element, $type) = $arr[$i]; if ($type == T_OPEN) $output[$current] = generate($arr, $i+1); elseif ($type == T_CLOSE) return $output; elseif ($type == T_FIELD) { $output[$element] = null; $current = $element; } } return $output; } $lex = new Lexer($tokenMap); $structure = $lex->lex($string); print_r(generate($structure));