Замена токенов в строке из массива - PullRequest
1 голос
/ 25 октября 2009

Допустим, у меня есть строка

Этот $ 0 равен $ 2 $ 1. Тем не менее, \ $$ 3 - это много, чтобы заплатить за щенка.

и массив замен

array('puppy', 'cute', 'ridiculously', '1300')

Каким был бы самый простой способ заменить токены в строке соответствующими элементами в массиве, позволяя мне экранировать от обратной косой черты символ токена (в данном случае $)? Я также хочу заменить несоответствующие токены пустой строкой.

Ответы [ 5 ]

4 голосов
/ 25 октября 2009
foreach ($array AS $key => $value)
{
    $string = str_replace('$' . $key, $value, $string);
}
1 голос
/ 25 октября 2009

Вот одна версия.

$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.

Он обрабатывает обратную косую черту перед $, чтобы экранировать эту переменную. Это может быть неудобным синтаксисом, потому что тогда вам нужно избегать обратной косой черты, что еще больше усложняет его (и в этом случае не обрабатывается). Регулярное выражение в основном означает $, за которым следуют одна или несколько цифр, если $ не предшествует обратная косая черта (с использованием негативного взгляда сзади ).

Он использует глобальный массив замен. Есть две альтернативы этому:

  1. Использовать замыкание (требуется PHP 5.3+); или
  2. Использование create_function().

Но я думаю, что глобальное проще и "глобально", если у вас нет веских причин делать что-то другое, несмотря на обычное отвращение к таким вещам.

1 голос
/ 25 октября 2009

Полагаю, вы имели в виду "\ $ 3", а не "\ $$ 3"

preg_replace('~(?<!\\\\)\$(\d+)~e', 'isset($array[$1])?$array[$1]:""', $source);

Кстати, знаете ли вы, что sprintf также допускает нумерованные параметры (http://php.net/manual/en/function.sprintf.php пример 3)

1 голос
/ 25 октября 2009
$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, как это можно сделать. Простое регулярное выражение и обратный вызов для замены. Реальная реализация зависит от того, что именно вы хотите с ней делать. Я надеюсь, что это помогло.

0 голосов
/ 25 октября 2009

Это решение следует за вопросом и немного заимствует из ответа Джоша Лейцеля. Несовпадающие шаблоны (например, $ 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 долларов - это очень много, чтобы заплатить за щенка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...