Моя текущая модель такова:
pattern=("/(.*)(\bIf you want\b)(.*)/iu");
Но с:
preg_replace($pattern, '$1*$2*$3', $result);
Таким образом, три части должны быть заменены на $ 1, $ 2 и $ 3, но я хочу дать некоторую дополнительную гибкость, чтобы я мог обнаружить, например, обе эти строки:
If you want
If I want
Так что я мог бы просто сделать это:
pattern=("/(.*)(\bIf (I|you) want\b)(.*)/iu");
но это создает проблему, так как мне нужно заменить $ 1, $ 2 и $ 3. Шаблоны вставляются динамически и поэтому все разные:
$pattern = "/(.*)(\b".$value."\b)(.*)/iu";
В $ value иногда есть модификатор, как в приведенном выше примере «if (you | I) want», но другие шаблоны могут быть просто «то, что произошло дальше» без модификатора. Таким образом, дополнительные скобки вызывают проблему, но я не могу найти другой способ сделать это.
РЕДАКТИРОВАТЬ: Обратите внимание, что проблема здесь с preg_replace $ 1, $ 2 и $ 3. С рисунком как
"/(.*)(\bwhat happened next\b)(.*)/iu"
это проходит нормально, но с дополнительной скобкой, как с
"/(.*)(\bIf (I|you) want\b)(.*)/iu"
он не заменит должным образом preg_replace за $ 1, $ 2 и $ 3.
Также я понимаю, что это можно сделать так
If you want|If I want
Но это не особенно красноречиво!
Проблема в том, что вы не можете полагаться на нумерованный группы захвата, так как их число может варьироваться, поскольку определенная пользователем часть шаблона может включать в себя произвольное количество пронумерованных групп захвата.
Выход может быть через использование названный захват групп. Единственная проблема с ними заключается в том, что PHP не поддерживает именованные обратные ссылки в шаблоне замены. Это можно обойти с помощью preg_replace_callback
функция:
$s = 'text If you want this';
echo preg_replace_callback("/(?<start>.*)(?<mid>If (I|you) want)(?<end>.*)/siu", function($m) {
return $m['start'].'*'.$m['mid'].'*'.$m['end'];
}, $s);
// => text *If you want* this
Увидеть PHP демо.
Вы можете «обфусцировать» имена групп, чтобы они не могли конфликтовать с пользовательскими шаблонами. Или сообщите пользователям, какие имена нельзя использовать внутри шаблона.
Заметка s
модификатор сделает .
разрывы линии матча также.
Приведенное выше решение будет соответствовать прошлой появление mid
группа как первая start
узор жадный точечный узор. Если ваша строка содержит несколько совпадений, и вы хотите сделать mid
группа соответствует первому вхождению в строке, замените (?<start>.*)
с (?<start>.*?)
, Иначе, вам нужно решить, каким должен быть алгоритм.
Для простого соответствия мне или вам, это сработало для меня:
$pattern=("/(.*)(\bIf (?:i|you) want\b)(.*)/iu");
Попробуй это:
pattern=("/(.*)(\bIf [I|you]+ want\b)(.*)/iu");