PHP preg_match_all search and replace

I've tried about a million different regular expressions, and I just can't wrap my head around this (admittedly, a lot of regular expressions from my understanding).

In my text, I have the following variables:

{{$one}} {{$three.four.five}} {{$six.seven}} 

And I have an array with all the replacements for them (index for "one" - "one", etc.), but some may be missing.

I want to replace from an array if it exists, and if you don't leave the text alone.

What can I use regex for preg_match_all variables in the text text in the fragment below, replace from $ replace where necessary, and echo in 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

It:

 '/\{\{\$(\w+)\}\}/e' 

as in the fragment, is the closest I received.

It should also work with the name do in variable names.

Thanks in advance for your help!

+8
php regex replace search preg-match
source share
4 answers

This is a very good example of using preg_replace_callback() , but first polish your regex:

  • Get rid of the e modifier, it is deprecated and you will not need it, since we will use preg_replace_callback()

     /\{\{\$(\w+)\}\}/ 
  • We don’t need to run {{}} , in this case PCRE is smart enough to say that they do not mean as quantifiers

     /{{\$(\w+)}}/ 
  • Since you have dots in your input, we need to change \w , otherwise it will never match. [^}] perfect because it means coinciding with anything other than }

     /{{\$([^}]+)}}/ 
  • I use different delimiters, this is not required:

     #{{\$([^}]+)}}# 

To get serious business, use identifier will be very useful 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 demo regex Online demo php

+8
source share

You do not need to use a regex for this, since you are dealing only with fixed lines:

 $replaces = array('testa.testb.testc' => 1, 'testc.testa' => 2, 'testf' => 3); $keys = array_map(function ($item) { return '{{$' . $item . '}}'; }, array_keys($replaces)); $trans = array_combine($keys, $replaces); $result = strtr($text, $trans); 

Note that array_map not required if you write an array of substitutions as follows:

 $trans = array('{{$testa.testb.testc}}' => 1, '{{$testc.testa}}' => 2, '{{$testf}}' => 3); 
+2
source share

Well, you just use $matches , not $matches[0] , so the code you posted doesn't work.

And your regular expression does not account . using \w , so let's try using [\w.]+

(I used $matches[1] , which directly contains 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}} 
+1
source share

You can also use the T-Regx library, which has automatic delimiters.

Use replace()->by()->mapIfExists() :

 $output = pattern('{{\$([^}]+)}}') ->replace('{{$testa.testb.testc}}<br>{{$testc.testa}}<br>{{$testf}}<br>{{$aaaaa}}<br>') ->all() ->by() ->group(1) ->mapIfExists([ 'testa.testb.testc' => '1', 'testc.testa' => '2', 'testf' => '3' ]); }); echo $output; 

This code does exactly what @HamZa answers, but with T-Regx :)

0
source share

All Articles