tags:

views:

31

answers:

3

I have the following sample template code.

{# @T('core.layout:Logged in as {0} {1}', @user('firstname'), @user('lastname')) #} {# VAR_TEST #}

And the following regex used to parse for the tags

/{# (\@)?(([A-Z][^#}]+)|(([a-zA-Z0-9\_]+)?\(([^#}]*)\))) #}/

However it only matches the last tag because of the close curly braces (}) in the first tag. I'm no expert in regex and thus the problem. I'm attempting to limit the matching by stopping the tags matching anything after the tag close #} by using the every character except #} pattern, ie [^#}]. However this is matching individual characters and not the #} string as a whole.

How to you write a regex to match everything but a string but not in character class mode?

Fyi, the regex flavour is PHP and preg_match.


Edit 1;

So I need to match

{# @T('core.layout:Logged in as {0} {1}', @user('firstname'), @user('lastname')) #}

and

{# VAR_TEST #}

with the same regex. however the first test match indicates a very complicated tag which is broken down with further regexes at a later point.

+1  A: 

Use a negative lookahead assertion: (?!#}).

But personally I would write the PCRE as: /{#.*?#}/ That's way more straightforward ;)

nikic
The trouble doing /{#.*?#}/ is that I would then have to break down every subsequent matched tag to get the tag parts out. But I suppose if this is a simpler regex it would be more optimal to run this and then parse out the tag data for each matched tag?
buggedcom
accepted as answer for suggesting the use of /{#.*?#}/ instead.
buggedcom
+1  A: 

Use a negative lookahead assertion:

(?:(?!#\}).)*

Explanation:

(?:      # match the following:
 (?!#\}) # assert that it's impossible to match #} here (but don't actually match it)
 .       # match any character
)*       # zero or more times
Tim Pietzcker
This does work also. Thanks very much for the regex comments.
buggedcom
+1  A: 

Try replacing [^#}]* with ([^#]|#[^}])*.

Aether
That does indeed work, thank-you.
buggedcom