Соответствие регулярного выражения PHP или одно слово без использования скобок?

Моя текущая модель такова:

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

Но это не особенно красноречиво!

2

Решение

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

Выход может быть через использование названный захват групп. Единственная проблема с ними заключается в том, что 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>.*?), Иначе, вам нужно решить, каким должен быть алгоритм.

0

Другие решения

Для простого соответствия мне или вам, это сработало для меня:

$pattern=("/(.*)(\bIf (?:i|you) want\b)(.*)/iu");
-1

Попробуй это:

pattern=("/(.*)(\bIf [I|you]+ want\b)(.*)/iu");
-3
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector