Question

my regular expression returns wrong strings

preg_replace_all("/\{\{([^W]+)\}\}/", $this->outputHtml,$matches);

I'm trying to match placeholders within template that have {{this}} syntax. What I'm getting matched is first occurence of {{ and last }} with all text in between including a lot of html.

Was it helpful?

Solution 2

The lazy repetition answers work great, but I personal avoid it when possible (since we can be more "specific" with what we want to match). I would use this expression:

\{{2}      (?# match 2 literal {)
(          (?# start capture group)
 [^}]+     (?# 1+ non } characters)
)          (?# end capture group)
\}{2}      (?# match 2 literal })

This captures 1+ non-} characters, meaning it will stop as soon as it sees the closing }}. However, this means a {{foo}bar}} template would not work (however, I don't think that would be a problem).

Implementation:

preg_replace_all("/\{{2}([^}]+)\}{2}/", $this->outputHtml, $matches);

OTHER TIPS

Make it ungreedy then:

preg_replace_all("/\{\{([^\W]+)\}\}/U", $this->outputHtml,$matches);

The U modifier is a PHP extension not originally present in Perl. Reference: Pattern Modifiers.

Edit — For the big picture (variable replacing in templates), I normally go the other way round: since I know the place-holder names in advance, I simply look for the literal tags and get them replaced with e.g. good old strtr(). E.g.:

// Totally untested code
$from = $to = array();
foreach($values as $key => $value){
    $from[] = "{{$key}}";
    $to[] = $value;
}
... = strtr($this->outputHtml, $from, $to);

Try using ? along with + to make it ungreedy (aka 'lazy'):

preg_replace_all("/\{\{([^W]+?)\}\}/", $this->outputHtml,$matches);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top