Допустим, у меня есть строка
Этот $ 0 составляет $ 2 $ 1. Тем не менее, \ $$ 3 много заплатить за щенка.
и множество замен
array('puppy', 'cute', 'ridiculously', '1300')
Каким будет самый чистый способ заменить токены в строке соответствующими элементами массива, разрешив мне обратную косую черту – избежать символа маркера (в данном случае $
)? Я также хочу заменить unmatched токены пустой строкой.
я думаю, вы имели в виду «\ $ 3», а не «\ $$ 3»,
preg_replace('~(?<!\\\\)\$(\d+)~e', 'isset($array[$1])?$array[$1]:""', $source);
Кстати, знаете ли вы, что sprintf также позволяет пронумеровать параметры ( http://php.net/manual/en/function.sprintf.php пример 3)
foreach ($array AS $key => $value) { $string = str_replace('$' . $key, $value, $string); }
$test_sub= 'This $0 is $2 $1. Still, \$$3 is a lot to pay for a puppy.'; $GLOBALS['replacers'] = array('puppy', 'cute', 'ridiculously', '1300'); echo preg_replace_callback('/[^\$]\$([0-9])+/', create_function( '$matches', 'return $matches[0][0] . $GLOBALS[\'replacers\'][$matches[1]];' ), $test_sub );
Это POC, как это можно сделать. Простое регулярное выражение и обратный вызов для замены. Фактическая реализация зависит от того, что именно вы хотите с ней сделать. Надеюсь, это помогло.
Вот одна версия.
$replacements = array('puppy', 'cute', 'ridiculously', '1300'); $input = 'This $0 is $2 $1. Still, \$3 is a lot to pay for a puppy.'; $output = preg_replace_callback('/(?<!\\\\)\$(\d+)/', 'replace_input', $input); echo $input . "<br>"; echo $output; function replace_input($matches) { global $replacements; $index = $matches[1]; return $index < 0 || $index >= count($replacements) ? $matches[0] : $replacements[$index]; }
Вывод:
This $0 is $2 $1. Still, \$3 is a lot to pay for a puppy. This puppy is ridiculously cute. Still, \$3 is a lot to pay for a puppy.
Он обрабатывает обратную косую черту перед $, чтобы избежать этой переменной. Это может быть неудобным синтаксисом, потому что тогда вам нужно избегать обратных косых черт, что еще больше усложняет его (и в этом случае не обрабатывается). Регулярное выражение в основном означает $, за которым следует одна или несколько цифр, если $ не предшествует обратная косая черта (используя отрицательный lookbehind ).
Он использует глобальный массив для замены. Есть две альтернативы этому:
create_function()
. Но я думаю, что глобальное проще и «глобально», если у вас нет веских оснований делать что-то другое, несмотря на обычное отвращение, которое мы испытываем к таким вещам.
Это решение следует за вопросом и немного заимствует ответ Джоша Лейцеля. Непревзойденные шаблоны (например, $ 4, $ 5) заменяются пустой строкой, удаляя их из ввода.
$input = "This $0 is $2 $1. Still, \$$3 is a lot to pay for a puppy."; $replacements = array('puppy','cute','ridiculously','1300'); $pattern = "/[$]{1}([0-9]{1})/"; preg_match_all($pattern, $input, $matches); if (isset($matches[1])) foreach ($matches[1] as $key => $value) { $input = str_replace("$".$value, $replacements[$value], $input); } echo $input;
Вывод:
Этот щенок смехотворно симпатичен. Тем не менее, $ 1300 – это много, чтобы заплатить за щенка.