Замена в строке регуляркой

307
22 марта 2017, 19:14

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

Строка вида [STRING_****] (STRING_*****) /STRING

Нужно заменить все STRING кроме /STRING при этом у меня почему то заменяются и скобки.

$file    = file_get_contents($_SERVER['DOCUMENT_ROOT'].'/uploads/data.txt');
$searchContext  = 'STRING';
$replaceContext = 'NEW_STRING';
$pattern = '/([\[(\s])('.$searchContext.')/';
$result = preg_replace($pattern, $replaceContext, $file);
Answer 1

В оригинальном регулярном выражении заданы 2 захватывающие группы (подмаска), каждая из которых создаёт буфер в памяти, в котором хранится часть совпадения:

'/([\[(\s])('.$searchContext.')/'
  | --1-- || ------ 2 ------- |

Содержимое этих двух групп можно "восстановить", т.е. обратиться к тексту в этих группах, с помощью обратных ссылок, которые можно использовать в шаблоне замены, используя следующий синтаксис: $ + идентификатор группы. Группа №1 — это шаблон, обрамлённый первой парой неэкранированных круглых скобок, в шаблоне замены надо использовать $1:

$result = preg_replace($pattern, "$1" . $replaceContext, $file);
                                 ^^^^

См. PHP-демо

Из описанного выше следует, что вторая захватывающая группа лишняя.

Есть ещё один способ. В захватывающей группе задан шаблон известной длины (([\[(\s]) находит один символ), поэтому можно просто преобразовать группу в блок предварительного просмотра назад и использовать

$pattern = '/(?<=[\[(\s])'.$searchContext.'/';
$result = preg_replace($pattern, $replaceContext, $file);

Ещё одно демо

Блоки предварительного просмотра не добавляют найденный текст в конечный массив значений, а также не меняет позицию в строке (т.е. шаблон этих блоков проверяется на наличие/отстутвие, а при выходе из блока поиск последующих шаблонов продолжается с того же места в строке, где начался поиск шаблона блока).

В PCRE, кроме двух описанных способов, можно воспользоваться оператором "сброса совпадения", \K:

preg_replace('/[\[(\s]\K'.$searchContext.'/', $replaceContext, $file)

И снова демо

Всё, что было найдено до \K, удаляется из буфера совпадения.

Примечание: Если в $searchContext ожидается наличие специальных метасимволов (операторов, таких как (, ), [, {, \, +, ^, $, *, ? и .), необходимо экранировать их с помощью preg_quote($searchContext, '/'). Второй параметр экранирует разделитель регулярного выражения (в данном случае, /).

READ ALSO
sql иньекция как исправить?

sql иньекция как исправить?

Скажите пожалуйста как иправить sql иньекцию, если $message будет "qwe'; DROP TABLE sel_category; --"

356
Запись данных в цикле

Запись данных в цикле

ЗдравствуйтеСуть проблемы: есть 4 поля в БД id, category_id,brands_id, models

298
Структура массива под SOAP запрос

Структура массива под SOAP запрос

У меня есть вот такой XML, который прекрасно работает в SOAPIU:

407