Используя preg_replace_callback
, можно ли заменить только одну preg_replace_callback
? Или мне нужно вернуть все это?
Я просто пытаюсь поместить значение маркера по умолчанию в кавычки.
$str = 'This is a {$token|token was empty}'; $str = preg_replace_callback('~{\$\w+\|(.*)?}~i', function($match) { //$match[1] is "token was empty" //I want to just replace $match[1], but it needs me to return the whole thing }, $str);
Должен ли я захватить больше обратных ссылок, чтобы я смог создать новую версию токена и вернуть его, я не могу просто заменить backreference 1? Благодарю.
Должен ли я захватить больше обратных ссылок, чтобы я смог создать новую версию токена и вернуть его, я не могу просто заменить backreference 1?
У вас есть два варианта:
Обычно я рекомендую использовать первый подход, так как второй бит менее эффективен и может приводить к недействительным совпадениям в некоторых случаях (когда просматриваемые и скрытые могут перекрываться). В этом случае не было бы проблем.
Пример второго варианта:
preg_replace_callback('~{\$\w+\|\K(?:[^{}]+)?(?=})~i', function($match){ // $match[0] contains what used to be the first capturing group. // return the value you want to replace it with // (you can still use the capturing group if you want, but it's unnecessary) });
\K
– это способ исключить все из него из фактического соответствия (например, если бы мы имели переменную длину lookbehind там). (?=})
– это взгляд, говорящий, что следующее должно быть a }
но не включает его в совпадение. Вместо этого вы хотите использовать регулярное выражение:
~\{\$(\w+?)(?:\|(.+?))?\}~i
Затем вы можете легко увидеть, что передается вашему обратному вызову:
$str = 'This is a {$token|token was empty}'; $str = preg_replace_callback('~\{\$(\w+?)(?:\|(.+?))?\}~i', function($match) { var_dump($match); exit; }, $str);
Вывод:
array(3) { [0]=> string(24) "{$token|token was empty}" [1]=> string(5) "token" [2]=> string(15) "token was empty" }
И оттуда вы можете проверить, установлен ли $match[1]
, и если да, верните его значение, в противном случае верните $match[2]
:
$foo = 'foo'; $str = 'Foo: {$foo|not set}, Bar: {$bar|not set}'; $str = preg_replace_callback('~\{\$(\w+?)(?:\|(.+?))?\}~i', function($match) { if (isset($GLOBALS[$match[1]])) { return $GLOBALS[$match[1]]; } else { return $match[2]; } }, $str); var_dump($str);
Вывод:
string(22) "Foo: foo, Bar: not set"
Примечание. Я использую $GLOBALS
здесь только для демонстрационных целей. Я бы предложил использовать привязку закрытия PHP 5.4, если это вообще возможно, с тех пор вы можете назначить закрытие определенного объекта как контекста (например, ваш объект шаблона / представления или что-то, что содержит переменные, которые вы пытаетесь заменить) , Если вы не используете PHP 5.4, вы также можете использовать function($match) use ($obj)
синтаксиса function($match) use ($obj)
, где $obj
– ваш контекст, а затем проверьте isset($obj->{$match[1]})
внутри вашего закрытия.
Недавно я придумал более простой способ сделать это. Например; если я хочу сопоставить \w+\d+\w+
и только изменить цифры.
$value = preg_replace_callback('~(\w+)(\d+)(\w+)~', function($match) { $match[2] = $match[2] * 2;//Do whatever I want to $match[2] return $match[1] . $match[2] . $match[3]; }, $value);
Очень чистый!