Here's one version.
$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];
}
Output:
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.
It handles a backslash before the $ to escape that variable. That could be an awkward syntax because then you need to escape backslashes, which complicates it further (and isn't handled in this case). The regular expression basically means $ followed by one or more digits as long as the $ isn't preceded by a backslash (using a negative lookbehind).
It uses a global for the replacements array. There are two alternatives to this:
- Use a closure (requires PHP 5.3+); or
- Use
create_function()
.
But I think the global is simpler and "global" unless you have a good reason to do something different in spite of the usual distaste we have for such things.