skip to Main Content

I’m trying to preg_replace() a string with a different replacement for each found match. Below is an example string and the pattern to look for:

$string = "111111Z not-a-match 000000Z not-a-match 000000Z";
$pattern = "/d{6}Z/";

I want to be able to replace the matches based on the order they were found. For example, replace the first match (‘111111Z’) with ‘FIRST’. Meaning my desired value would be something like:

$newString = "FIRST not-a-match SECOND not-a-match THIRD"

What is the best way to get from $string to $newString?

I’ve been looking into setting a $matches variable in either a preg_match_all() or a preg_replace_callback(), and then loop through each match, but I’m struggling to get back around to the full original string with the matches replaced.

4

Answers


  1. One way is preg_replace_callback(), using an extra array with the replacements:

    $string = "111111Z not-a-match 000000Z not-a-match 000000Z";
    $pattern = "/d{6}Z/";
    
    $newString = "FIRST not-a-match SECOND not-a-match THIRD";
    $returns = [
      'FIRST', 'SECOND', 'THIRD'    
    ];
    
    $result = preg_replace_callback($pattern, function(array $matches) use(&$returns) {
        return array_shift($returns);
    }, $string);
    
    var_dump($newString, $result);
    

    Output

    string(42) "FIRST not-a-match SECOND not-a-match THIRD"
    string(42) "FIRST not-a-match SECOND not-a-match THIRD"
    
    Login or Signup to reply.
  2. To solve this, you can use preg_replace_callback() in PHP, which allows you to define a custom function to handle each match. This custom function will keep track of the match order and replace each match with the corresponding value (‘FIRST’, ‘SECOND’, ‘THIRD’, etc.).

    <?php
    $string = "111111Z not-a-match 000000Z not-a-match 000000Z";
    $pattern = "/d{6}Z/";
    
    $replacements = ['FIRST', 'SECOND', 'THIRD'];
    $index = 0;
    
    $newString = preg_replace_callback($pattern, function($match) use (&$index, $replacements) {
        return $replacements[$index++];
    }, $string);
    
    echo $newString;
    ?>
    
    Login or Signup to reply.
  3. You can try this

        // Define a callback function for replacement
    function replaceCallback($matches) {
        static $count = 0;
        $replacements = ['FIRST', 'SECOND', 'THIRD'];
        
        // Replace each match with the corresponding word
        if ($count < count($replacements)) {
            return $replacements[$count++];
        }
        
        // Return the original match if there are no more replacements
        return $matches[0];
    }
    
     $string = "111111Z not-a-match 000000Z not-a-match 000000Z";
        $newString = preg_replace_callback('/d+Z/', 'replaceCallback', $string);
        dd($newString);
    

    OUTPUT

    "FIRST not-a-match SECOND not-a-match THIRD"
    
    Login or Signup to reply.
  4. Use preg_replace() with the replacement limit optional argument, so it only replaces each match once before going to the next element of the pattern and replacement arrays.

    $newString = preg_replace([$pattern, $pattern, $pattern], ['FIRST', 'SECOND', 'THIRD'], $string, 1);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search