Страницы

Поиск по вопросам

пятница, 14 февраля 2020 г.

Построение выражения для получения элемента массива

#php #регулярные_выражения #pcre


Вообщем требуется превратить #$test.a# в $test['a'].

Делаю это так: preg_replace('@\#(\$.+?)\.(.+?)\#@', '$1[\'$2\']', '#$test.a#', -1);

Всё работает: https://xrg.es/#1ibiack

Но не знаю как превратить #$test.a.b.c# в $test['a']['b']['c'].

Помогите... Заранее спасибо!
    


Ответы

Ответ 1



не знаю как превратить #$test.a.b.c# в $test['a']['b']['c'] Вначале найти совпадения подстроки между решётками '#...#'. Потом разбить найденную подстроку на элементы по символу '.'. Далее, из полученного массива извлечь первый элемент (это название переменной), а оставшуюся часть обработать циклом, собирая строку необходимого формата в результирующую переменную $out: $str = '#$test.a.b.c#'; // Сработает $str = '#$test.a#'; // Сработает $str = '#$test.#'; // Не сработает $str = '#$test#'; // Не сработает echo preg_replace_callback( '~#(\$[a-z]+\d*\.[^#]+)#~', function ($arr) { $tmp = explode('.', $arr[1]); $out = array_shift($tmp); foreach ($tmp as $i) $out .= "['$i']"; $out .= ';'; return $out; }, $str ); Результат $test['a']['b']['c']; Следует помнить, что полученная строка не является массивом, а только выглядит как массив визуально.

Ответ 2



Всё можно сделать одной регуляркой с использованием оператора \G: '~(?:#(\$[^.#]+)(?=\.[^#]*#)|\G(?!^))\.([^#.]+)#?~' См. демо регулярного выражения. Подробности (?:#(\$[^.#]+)(?=\.[^#]*#)|\G(?!^)) - одно из двух: #(\$[^.#]+)(?=\.[^#]*#) - последовательность: # - знак #, (\$[^.#]+) - Захватывающая группа №1: $, один и более символов, отличных от . и # (?=\.[^#]*#) - после которых есть знак ., 0+ знаков, отличных от #, а затем # | - или \G(?!^) - позиция в строке после предыдущего удачного совпадения \. - знак . ([^#.]+) - Захватывающая группа №2: 1+ знаков, отличных от . и # #? - 1 или 0 знаков #. Пример на PHP: $re = '@(?:#(\$[^.#]+)(?=\.[^#]*#)|\G(?!^))\.([^#.]+)#?@'; $str = '#$test.a.b.c# #$test.a#'; echo preg_replace($re, '$1[\'$2\']', $str); // => $test['a']['b']['c'] $test['a']

Ответ 3



Как то так preg_replace("@\#(\$.+?)\.(.+?)\.(.+?)\.(.+?)\#@", "$1['$2']['$3']['$4'];", "#$test.a.b.c#", -1); PS. Но если там может быть разное количество переменных, то это будет сложнее сделать.

Ответ 4



За входние данные можно взять $string = '#$test_23.a.b.c#'; Напишу небольшую функцию которая будет делать то что нужно и возвращать результат или FALSE если будут невалидные данные Для начала проверим что слева действительно валидное название переменной. Оно как известно начинаеться со знака доллара ($) Потом должна идти одна буква латинского алфавита или нижнее подчеркивание ([a-zA-Z_]) Дальше в названии переменной может идти любая цифра, буква латинского алфавита или знак подчеркивания (\w). Символ * указывает на то что их может быть 0 или больше. Тоесть их может и не быть. Справа может быть или не быть продолжение название переменной function transform($string){ if(preg_match('@#(\$[a-zA-Z_]\w*)\.?([\w.]+)?#@', $string, $match)){ if(empty($match[2])){ return $match[1]; } $replace_string = "['" . preg_replace('@(\w)\.@', "$1']['", $match[2]) . "']"; return $match[1] . $replace_string; } return FALSE; }

Комментариев нет:

Отправить комментарий