2

I want to replace some numbers in a string with the content of the array in the position which this number points to.

For example, replace "Hello 1 you are great", with "Hello myarray[1] you are great"

I was doing the next: preg_replace('/(\d+)/','VALUE: ' . $array[$1],$string);

But it does not work. How could I do it?

Mark Tower
  • 559
  • 1
  • 5
  • 15
  • Do your actual use cases need regexes? – Waleed Khan Feb 25 '13 at 15:31
  • Why are you doing this? It sounds like you are building some sort of template system. It kinda sounds like an [xy problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – Nanne Feb 25 '13 at 15:32
  • 1
    Afaik the `$1` is only replaced in *string* values where it literally appears (not sure how PHP does it with its inline variables). Try [`preg_replace_callback`](http://php.net/manual/en/function.preg-replace-callback.php) – Bergi Feb 25 '13 at 15:33
  • @Nanne hmmm... it was funny, but this is not really and XY problem. I would say it is an **XYZ** one, because I need to solve X, and I am using method Y, but in order to make my question look more simple, I imagine a situation Z. I need to replace some concrete Ids in a string with a string which contains data from a database, but are already in an array. I could use a callback function instead but... isn't there any other more direct solution?. Thanks! – Mark Tower Feb 25 '13 at 15:36

4 Answers4

6

You should use a callback.

<?php
$str = 'Hello, 1!';
$replacements = array(
    1 => 'world'
);
$str = preg_replace_callback('/(\d+)/', function($matches) use($replacements) {
    if (array_key_exists($matches[0], $replacements)) {
        return $replacements[$matches[0]];
    } else {
        return $matches[0];
    }
}, $str);
var_dump($str); // 'Hello, world!'

Since you are using a callback, in the event that you actually want to use a number, you might want to encode your strings as {1} or something instead of 1. You can use a modified match pattern:

<?php
// added braces to match
$str = 'Hello, {1}!';
$replacements = array(
    1 => 'world'
);

// added braces to regex
$str = preg_replace_callback('/\{(\d+)\}/', function($matches) use($replacements) {
    if (array_key_exists($matches[1], $replacements)) {
        return $replacements[$matches[1]];
    } else {
        // leave string as-is, with braces
        return $matches[0];
    }
}, $str);
var_dump($str); // 'Hello, world!'

However, if you are always matching known strings, you may want to use @ChrisCooney's solution because it offers less opportunity to screw up the logic.

Community
  • 1
  • 1
Waleed Khan
  • 11,426
  • 6
  • 39
  • 70
  • Thank you, just had to search for the **use identifier**. http://stackoverflow.com/questions/1065188/in-php-5-3-0-what-is-the-function-use-identifier-should-a-sane-programmer-us – Mark Tower Feb 25 '13 at 15:46
  • 1
    `trim($matches[0], '{}');` - uh? Shouldn't you just use the appropriate capturing groups, i.e. `/\{(\d+)\}/`? – Bergi Feb 25 '13 at 16:06
  • @Bergi You are correct. I had thought for some reason the callback should return the replacement for the capture group only, but that of course makes no sense if there are multiple capture groups. Edited. – Waleed Khan Feb 25 '13 at 16:11
2

The other answer is perfectly fine. I managed it this way:

    $val = "Chris is 0";
    // Initialise with index.
    $adj = array("Fun", "Awesome", "Stupid");
    // Create array of replacements.
    $pattern = '!\d+!';
    // Create regular expression.
    preg_match($pattern, $val, $matches);
    // Get matches with the regular expression.
    echo preg_replace($pattern, $adj[$matches[0]], $val);
    // Replace number with first match found.

Just offering another solution to the problem :)

christopher
  • 26,815
  • 5
  • 55
  • 89
0
$string = "Hello 1 you are great";
$replacements = array(1 => 'I think');

preg_match('/\s(\d)\s/', $string, $matches);

foreach($matches as $key => $match) {
  // skip full pattern match
  if(!$key) {
    continue;
  }
  $string = str_replace($match, $replacements[$match], $string);
}
  • This loses most of the flexibility in using a regex. What if you actually wanted to replace a regular expression? – Waleed Khan Feb 25 '13 at 15:50
0
<?php
$array = array( 2 => '**', 3 => '***');
$string = 'lets test for number 2 and see 3 the result';
echo preg_replace_callback('/(\d+)/', 'replaceNumber', $string);

function replaceNumber($matches){
 global $array;
 return $array[$matches[0]];
}
?>

output

lets test for number ** and see *** the result