chtombleson
chtombleson

Reputation: 33

Regex not getting all matches

Basically I'm writing a small template parser that uses regex to parse some tags, at the moment I'm having trouble with matching multiple tags in the same file.

Here is my current regex pattern:

$regex = '#\{if \$([A-Za-z0-9_]+)\}([^{]+)(\{else\})?([^{]+)?\{\/if\}#'

Am I missing something here?

Here an example of a template file I'm trying to parse

{if $name}
   Hi my name is: {$name}.
{else}
   No name set.
{/if}

{if $male}
   Gender: Male.
{else}
   Gender: Female.
{/if}

Here is my php code as it stands at the moment:

<?php
$tpl_file = file_get_contents('template.tpl');
$regex = '#\{if \$([A-Za-z0-9_]+)\}([^{]+)(\{else\})?([^{]+)?\{\/if\}#';

if (preg_match_all($regex, $tpl_file, $matches)) {
   print_r($matches);
}
?>

Any help is greatly appreciated. Cheers

Upvotes: 0

Views: 188

Answers (2)

Mark
Mark

Reputation: 1088

Regex is tragically, tragically poor at dealing with matching nested closures. Anything with start and end structures are closures and stuffing them inside each other or dealing with them on meta-levels is super hard.

See the top answer to this post more specifically about (X)HTML RegEx match open tags except XHTML self-contained tags and then consider that you've basically reinvented a procedure-XML-like syntax with different braces.

Regex is for "regular expression" matching. Unfortunately for you, "regular" doesn't mean what it regularly means but is instead a mathematical catchphrase for a particular type of problem.

Upvotes: 1

cambraca
cambraca

Reputation: 27839

You shouldn't make such a parser using regex. It's just not possible. Anyway, as Francis said, if you remove the {$name} from the first if block, it will match using your existing code.

Upvotes: 1

Related Questions