I have tried about a million different regexes and I just can't wrap my head around this one (admittedly a lot of regex is out of my grasp).
In my text I have variables like this:
{{$one}}
{{$three.four.five}}
{{$six.seven}}
And I have an array with all the replaces for them (the index for 'one' is 'one' etc) but some may be missing.
I want to replace from the array if it exists and if not leave the text alone.
What regex can I use to preg_match_all of the variables in $text in the snippet below, replace from $replace where appropriate and echo out to the browser?
<?php
$replaces = array('testa.testb.testc' => '1', 'testc.testa' => '2', 'testf' => '3');
$text = '{{$testa.testb.testc}}<br>{{$testc.testa}}<br>{{$testf}}<br>{{$aaaaa}}<br>';
preg_match_all('/\{\{\$(\w+)\}\}/e', $text, $matches);
foreach($matches as $match)
{
$key = str_replace('{{$', '', $match);
$key = str_replace('}}', '', $key);
if(isset($replaces[$key]))
$text = str_replace($match, $replaces[$key], $text);
}
// I want to end up echo'ing:
// 1<br>2<br>3<br>{{$aaaaa}}<br>
echo $text;
?>
http://codepad.viper-7.com/4INvEE
This:
'/\{\{\$(\w+)\}\}/e'
like in the snippet, is the closest I have gotten.
It has to work with the does in the variable names too.
Thanks in advance for all the help!
preg_match stops looking after the first match. preg_match_all , on the other hand, continues to look until it finishes processing the entire string. Once match is found, it uses the remainder of the string to try and apply another match.
The preg_match_all() function returns the number of matches of a pattern that were found in a string and populates a variable with the matches that were found.
str_replace replaces a specific occurrence of a string, for instance "foo" will only match and replace that: "foo". preg_replace will do regular expression matching, for instance "/f. {2}/" will match and replace "foo", but also "fey", "fir", "fox", "f12", etc.
This is a very good case for using preg_replace_callback()
but first let's polish your regex:
Get rid of the e
modifier, it's deprecated and you don't need it since we're going to use preg_replace_callback()
/\{\{\$(\w+)\}\}/
We don't need to escape {{}}
in this case, PCRE is smart enough to tell that they are not meant as quantifiers
/{{\$(\w+)}}/
Since you got dots in your input, we need to change \w
otherwise it will never match. [^}]
is perfect since it means match anything except }
/{{\$([^}]+)}}/
I tend to use different delimiters, this is not required:
#{{\$([^}]+)}}#
Let's get to serious business, the use
identifier is going to be of great help here:
$replaces = array('testa.testb.testc' => '1', 'testc.testa' => '2', 'testf' => '3');
$text = '{{$testa.testb.testc}}<br>{{$testc.testa}}<br>{{$testf}}<br>{{$aaaaa}}<br>';
$output = preg_replace_callback('#{{\$([^}]+)}}#', function($m) use ($replaces){
if(isset($replaces[$m[1]])){ // If it exists in our array
return $replaces[$m[1]]; // Then replace it from our array
}else{
return $m[0]; // Otherwise return the whole match (basically we won't change it)
}
}, $text);
echo $output;
Online regex demo Online php demo
Well you are just using $matches
and not $matches[0]
, that's why the code you posted does not work.
And your regex doesn't count the .
with the \w
, so let'z try with [\w.]+
(I used $matches[1]
that contains directly the key we need, and then we don't need to use str_replace 2 times more)
$replaces = array('testa.testb.testc' => '1', 'testc.testa' => '2', 'testf' => '3');
$text = '{{$testa.testb.testc}}<br>{{$testc.testa}}<br>{{$testf}}<br>{{$aaaaa}}<br>';
preg_match_all('/\{\{\$([\w.]+)\}\}/', $text, $matches);
var_dump($matches[1]);
foreach($matches[1] as $match)
{
if(isset($replaces[$match]))
{
$text = str_replace('{{$'.$match.'}}', $replaces[$match], $text);
}
}
echo $text;
This works and returns :
1
2
3
{{$aaaaa}}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With