Нужна помощь с preg_replace

119
19 февраля 2018, 03:51

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

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

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

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

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

Answer 1

Всё можно сделать одной регуляркой с использованием оператора \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']
Answer 2

не знаю как превратить #$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'];

Следует помнить, что полученная строка не является массивом, а только выглядит как массив визуально.

Answer 3

Как то так

preg_replace("@\#(\$.+?)\.(.+?)\.(.+?)\.(.+?)\#@", "$1['$2']['$3']['$4'];", "#$test.a.b.c#", -1);

PS. Но если там может быть разное количество переменных, то это будет сложнее сделать.

Answer 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;
}
READ ALSO
Создание PDF файла средствами php

Создание PDF файла средствами php

Добрый деньНеобходимо создать pdf документ в корзине пользователя для сайта на системе управления 1С-Битрикс

99
Не переходит на созданные страницы

Не переходит на созданные страницы

Добрый деньЯ у меня самописаный сайт на php

112
Как правильно составить и ответить на длинные опрос?

Как правильно составить и ответить на длинные опрос?

Здравствуйте! Пытаюсь сделать длинный опросТо есть я хочу сделать так, что бы клиент не посылал очередной запрос до того, как не прешел ответ...

125
DLE исполнение кода в новости

DLE исполнение кода в новости

Суть в общем в чем!? , имеется сайт для новичков хочу сделать раздел примеры кода движок DLE, хотелось бы сделать каким то образом исполнение...

139