5

I need some help with creating a regex for my php script. Basically, I have an associative array containing my data, and I want to use preg_replace to replace some place-holders with real data. The input would be something like this:

<td>{{address}}</td><td>{{fixDate}}</td><td>{{measureDate}}</td><td>{{builder}}</td>

I don't want to use str_replace, because the array may hold many more items than I need.

If I understand correctly, preg_replace is able to take the text that it finds from the regex, and replace it with the value of that key in the array, e.g.

<td>{{address}}</td>

get replaced with the value of $replace['address']. Is this true, or did I misread the php docs?

If it is true, could someone please help show me a regex that will parse this for me (would appreciate it if you also explain how it works, since I am not very good with regexes yet).

Many thanks.

a_m0d
  • 12,034
  • 15
  • 57
  • 79

3 Answers3

10

Use preg_replace_callback(). It's incredibly useful for this kind of thing.

$replace_values = array(
  'test' => 'test two',
);
$result = preg_replace_callback('!\{\{(\w+)\}\}!', 'replace_value', $input);

function replace_value($matches) {
  global $replace_values;
  return $replace_values[$matches[1]];
}

Basically this says find all occurrences of {{...}} containing word characters and replace that value with the value from a lookup table (being the global $replace_values).

Jean-Bernard Pellerin
  • 12,556
  • 10
  • 57
  • 79
cletus
  • 616,129
  • 168
  • 910
  • 942
  • Thanks, that seems to be just what I was after. – a_m0d Jun 06 '09 at 05:03
  • 1
    I would allow zero or more spaces around the actual term making the regex pattern `'!\{\{\s?(\w+)\s?\}\}!'` therefore allowing not only `{{term}}` but also `{{ term}}`, `{{term }}` and `{{ term }}` – Michael Feb 19 '17 at 19:02
0

To not have to use global variables and gracefully handle missing keys you can use

function render($template, $vars) {
        return \preg_replace_callback("!{{\s*(?P<key>[a-zA-Z0-9_-]+?)\s*}}!", function($match) use($vars){
            return isset($vars[$match["key"]]) ? $vars[$match["key"]] : $match[0];
        }, $template);
    }
mleko
  • 11,650
  • 6
  • 50
  • 71
0

For well-formed HTML/XML parsing, consider using the Document Object Model (DOM) in conjunction with XPath. It's much more fun to use than regexes for that sort of thing.

xyz
  • 1,242
  • 9
  • 13
  • 1
    While that's a reasonable stance if you're actually doing text searches on HTML tags or attributes, this template syntax is so specific (double curly braces) that you don't have the normal HTML regex problems because that character sequence pretty much can't occur except where you want it to. HTML regex parsing is flaky but that's not this situation. – cletus Jun 06 '09 at 06:06