5

Seems like this should be straightforward but the following code is not working:

$text = preg_replace('/test([0-9]+)/i', $array["$1"], $text);

The code is supposed to find all instances like 'test1', 'test2', 'test3', etc. in a text and replace with the values of $array[1], $array[2], $array[3], etc.

What am I doing wrong?

2
  • 2
    You want to use preg_replace_callback() and pass the array via use() to it, Commented Mar 30, 2016 at 17:33
  • The second argument for preg_replace takes in a replacement string, which can contain references in the form of $n. These aren't php variables so you can't use them the way you want. Commented Mar 30, 2016 at 17:42

2 Answers 2

7

You need to use a callback:

$text = preg_replace_callback('/(test)([0-9]+)/i', 
                              function($m) use($array) { return $m[1].$array[$m[2]]; },
                              $text);

The function takes the matches and uses the first capture group match concatenated with the array item with the second capture group match as the index. You might want an if in there to check that $array[$m[2]] exists first.

Alternatively you could use a loop:

foreach($array as $key => $val) {
    $text = str_replace("test$key", "test$val", $text);
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks! Brilliant!
I have no clue what's going on. Could you please explain what $m is for and what $m[1].$array[$m[2]] means?
$m is an array of the matches so $m[1] is the match from the first capture group ()
2

You already have the answer. This one is only to explain better than in comments your assumption error.

$1 is not a result of first parameter, it is a placeholder used only by preg_replace itself. Your use invoke also the commands precedence.

In other words, if you try this code:

$text = 'Lorem test8 Dolor';
function test( $arg ) { echo $arg.PHP_EOL; }
$text = preg_replace('/test([0-9]+)/i', test("$1"), $text);
echo $text;

You obtain this output:

$1
Lorem  Dolor

As you can see, first argument is evaluated, then the result is used by preg_replace: test() function receive literally $1 (and in the same way your array), not the 8 retrieved by preg_replace; then preg_replace replace matched substring by value returned in second argument: in above case test() returns nothing, so the replacement is nothing.

With this code:

function test() { return '[$1]'; }
$text = preg_replace('/test([0-9]+)/i', test(), $text);

The resulting string is:

Lorem [8] Dolor

because test() returns [$1] and it can be used by preg_replace to perform the replacement.

In your specific case, the replacement happen only if you have a scenario like this one:

$array["$1"] = 'Ipsum';
$text = preg_replace('/test([0-9]+)/i', $array["$1"], $text);

The final text is:

Lorem Ipsum Dolor

This is not your desired result, but — as mentioned earlier — you already have the answer...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.