3

I'm getting stuck at this problem, which is

I have an array like this:

$array = [
    'name' => 'John',
    'email' => [email protected]
];

And a string sample like this:

$string = 'Hi [[name]], your email is [[email]]';

The problem is obvious, replace name with John and email with [email protected].

What i attempted:

//check if $string has [[ ]] pattern

$stringHasBrackets = preg_match_all('/\[\[(.*?)\]\]/i', $string,  $matchOutput);

if ($stringHasBrackets) {

    foreach ($matchOutput[1] as $matchOutputKey => $stringToBeReplaced) {

        if (array_key_exists($stringToBeReplaced, $array)) {

            $newString = preg_replace("/\[\[(.+?)\]\]/i",
                            $array[$stringToBeReplaced],
                            $string);

        }
    }
}

Which led me to a new string like this:

Hi [email protected], your email is [email protected]

Makes sense because that's what the pattern is for, but not what I wanted.

How can I solve this? I thought of using a variable in the pattern but don't know how to do it. I've read about preg_replace_callback but also don't really know how to implement it.

Thanks!

4 Answers 4

4

You may use preg_replace_callback like this:

$array = ['name' => 'John', 'email' => '[email protected]'];
$string = 'Hi [[name]], your email is [[email]]';
echo preg_replace_callback('/\[\[(.*?)]]/', function ($m) use ($array) {
        return isset($array[$m[1]]) ? $array[$m[1]] : $m[0]; 
    }, $string);

See PHP demo.

Details

  • '/\[\[(.*?)]]/' matches [[...]] substrings putting what is inside the brackets into Group 1
  • $m holds the match object
  • use ($array) allows the callback to access $array variable
  • isset($array[$m[1]]) checks if there is a value corresponding to the found key in the $array variable. If it is found, the value is returned, else, the found match is pasted back.
Sign up to request clarification or add additional context in comments.

4 Comments

Nice answer +1 @DuongNguyen But because running regex is pretty expensive operation . i would include a if to check if the string contains a replace templates checking on [[ and ]] see demo ideone.com/K4hKmJ .. Nicer would be offcource to make a function
Thanks. Will do a research on preg_replace_callback and get back to you if this works. @RaymondNijland I checked the string with preg_match_all, is it alright?
"I checked the string with preg_match_all, is it alright?" @DuongNguyen preg_match_all still uses regexes now you start up two regex engines.
@RaymondNijland I see.
3

preg_replace accepts arrays as regex and replacement so you can use this simpler approach:

$array = ['name' => 'John', 'email' => '[email protected]'];
$string = 'Hi [[name]], your email is [[email]]';

// create array of regex using array keys
$rearr = array_map(function($k) { return '/\[\[' . $k . ']]/'; },
         array_keys($array));

# pass 2 arrays to preg_replace
echo preg_replace($rearr, $array, $string) . '\n';

Output:

Hi John, your email is [email protected]

PHP Code Demo

3 Comments

Gotta do another research on using array_map :D
array_map is used to convert each key into regex. So name becomes /\[\name]]/
@bobblebubble: You're right, array_values isn't needed.
1

You can try this,

$array = ['name' => 'John', 'email' => '[email protected]'];
$string = 'Hi [[name]], your email is [[email]]';
$stringHasBrackets = preg_match_all('/\[\[(.*?)\]\]/i', $string,  $matchOutput);

if ($stringHasBrackets) {
    $newString = $string;
    foreach ($matchOutput[1] as $matchOutputKey => $stringToBeReplaced) {
        if (array_key_exists($stringToBeReplaced, $array)) {
            $newString = preg_replace("/\[\[$stringToBeReplaced\]\]/i", $array[$stringToBeReplaced], $newString);
        }
    }
    echo $newString;
}

2 Comments

Thanks! This works like a charm. I'm not a regex wizard but how did you know where to put the variable?
@DuongNguyen, Thanks :)
1

I think here more simply would be to use str_replace function, like:

$array = [
          'name' => 'John',
          'email' => '[email protected]'
          ];

$string = 'Hi [[name]], your email is [[email]]';
$string = str_replace(array_map(function ($v) {return "[[{$v}]]";}, 
                      array_keys($array)), $array, $string);
echo $string;

Updated for $array to be "untouchable"

3 Comments

This can be much simpler than using regex, but I'm not allowed to touch the array, and array_keys returns an array, so can I somehow concatenate [[ and ]] to it? Also, I want to replace array_keys($array) in the string with array values.
see updated version - in this case we need array_map also. And yes - it searches in string for modified keys and replaces with array values
Thank you Agnius!

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.