2016-02-10 2 views
0

У меня есть строка $src с двумя переменными заполнителями %%itemA%% и %%itemB%%. Идея состоит в том, что регулярное выражение соответствует любому термину, указанному ITEMA|ITEMB|ITEMC, без учета регистра и заменяет термин значением элемента массива, используя этот термин в качестве ключа массива.PHP preg_replace с переменным значением, используя найденное выражение как ключ

$replacements = [ 
    'itemA' => 'replacedItemA', 
    'itemB' => 'replacedItemB', 
    'itemC' => 'replacedItemC' 
]; 

$src = "A B C %%itemA%% D E F %%itemB%% G H I"; 

$src = preg_replace('/\%\%(ITEMA|ITEMB|ITEMC)%%/i', $replacements['\1'], $src); 

echo $src; 

В этом примере ожидаемый результат для %%itemA%% должен быть заменен $replacements['itemA'] «значение с и %%itemB%% быть заменены $replacements['itemB']» значение s

Ожидаемые результаты от echo был

ABC замененItemA заменен DEFItemB GHI

Фактический выход, как ни странно, просто заменить найденные термины ни с чем (обратите внимание на двойные пробелы, где была удалена переменная)

A B C D E F G H I

Почему строка Термин не используется в $replacements['key'] использовать значение переменной массива?

ответ

2

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

$replacements = [ 
    '%%itemA%%' => 'replacedItemA', 
    '%%itemB%%' => 'replacedItemB', 
    '%%itemC%%' => 'replacedItemC' 
]; 

$str = strtr($str, $replacements); 
+0

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

+1

@CraigMcArthur: «Я понимаю, что регулярное выражение более эффективно»: это абсолютно ложная идея! –

+0

Если нет необходимости также модифицировать '$ replacements' и указать некоторый дополнительный контекст для строк' %% ... %%', это также можно использовать. Regex позволяет еще несколько вещей, которые просто «strtr' не делает. –

0

Вам просто нужно заменить preg_replace с preg_replace_callback, как это:

$src = preg_replace_callback('/%%(ITEM[ABC])%%/i', function ($m) use ($replacements) { 
return isset($replacements[$m[1]]) ? $replacements[$m[1]] : $m[0]; 
} 
, $src); 

См IDEONE demo

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

Я также немного сократил образец, но я думаю, что это всего лишь образец.

Смежные вопросы