How to make this Regex more flexible? I am creating a simple template engine that uses Regex to find special expressions, which are parsed and processed. They are enclosed in Ruby-style opening tags and have the format:

    &lt;% label %&gt;  OR:
    &lt;% function(arg1, arg2, arg3) %&gt;


However the problem is that I cannot have multiple entries on the same line, so I can't have this:

    &lt;p&gt;&lt;% name %&gt; - &lt;% age %&gt; - &lt;% gender %&gt;&lt;/p&gt;


Instead I have to write it like this:

    &lt;p&gt;&lt;% name %&gt; - 
       &lt;% age %&gt; -
       &lt;% gender %&gt;&lt;p&gt;


How can I fix this? Below I included the code for the function that handles this. Basically what it does is read from a file, split everything line by line, then iterate through each line and do a regex match and return the results. 

public function content()
{
    if (!file_exists($this-&gt;path))
        return;

    /* 0 = before, 1 = entry #1, 2 = entry #2, 3 = after */
    $content = file_get_contents($this-&gt;path); 
    $pattern = '/^(.*)\&lt;\%\s*(.+)\s*\%\&gt;(.*)$/'; 
    $lines = explode("\n", $content); 


    foreach ($lines as $line)
    {
        // Pattern match the line
        preg_match($pattern, $line, $matches); 

        $result = ''; 

        // If there are no matches, then don't parse it and add the raw string to output
        if (count($matches) == 0)
        {
            continue; 
        }   


        // Parse the matches and run the appropriate action         
        $before = $matches[1]; 
        $after = $matches[3]; 
        $entry = $matches[2]; 
        $return = ''; 


        // Process the entry
        $return = $this-&gt;processEntry($entry);

        // Add the processed line to the final result if not empty
        $result = $before . $return . $after; 
        if (!empty($result)) $final .= $result . "\n"; 
    }
    return $final; 
}
What to you thing about:

&lt;?=label ?&gt;  OR:
&lt;?=function(arg1, arg2, arg3) ?&gt;


PHP is already a template engine

Just write a wrapper around a include call and your template system is ready to use and more flexible than anything you could write.



That said, why to you match single lines? Please have a look at preg_replace_callback.

/\&lt;\%\s*(.+?)\s*\%\&gt;/


If you want to put the whitespace trimming in the callback and as you don't need to escape &lt;&gt;%, you could even use

/&lt;%(.+?)%&gt;/