3

I use the following pattern to match and replace a simple IF-ELSE-ENDIF block using preg_replace_callback:

##IF (.*?)##(.*?)(?:##ELSE##(.*?))?##ENDIF##

The following two examples are matched and replaced correctly

1. ##IF x()## foo ##ENDIF##

Result:

Group 1: `x()`
Group 2: ` foo `

2. ##IF y()## foo ##ELSE## bar ##ENDIF##

Result:

Group 1: `y()`
Group 2: ` foo `
Group 3: ` bar `

Now I want to enhance this functionality to allow nested IF-ELSE blocks, e.g.

##IF g()## pre-outer-if ##IF h()## inner-if ##ENDIF## post-outer-if ##ELSE## outer-else ##ENDIF##

Here is a demo on regex101.com.

I played around to enhance the pattern with the recursion operator and positive lookaheads but I did not succeed. The goal is to match and replace related IF-ELSE-ENDIF blocks to allow a user to define conditional textblocks.

If possible, I want to avoid writing a language parser for this enhancement.

Thanks a lot for any suggestion!

2
  • What exactly are you doing with the matches? Please share the method with preg_replace_callback. Commented Jul 26, 2018 at 13:03
  • @Wiktor: The blocks are part of a bigger text and allows the users of the system to create dynamic text modules based on those conditions. The whole condition is replaced by either the ##IF## or the ##ELSE## part. The functions x(), y() or g() are just examples for a set of user defined functions. Commented Jul 26, 2018 at 13:10

1 Answer 1

2

Try this:

##IF (?>(.*?)##)((?>(?0)|.)*?)(?:##ELSE##((?>(?0)|.)*?))?##ENDIF##

It will find a outer if-block groups.

Sign up to request clarification or add additional context in comments.

2 Comments

Deleted my last comment because it was wrong. This regex seems to work fine. I use it inside a loop until no more ##IF## statements are found. Could you explain why the first atomic group (?>(.*?)##) is necessary?
It effectively reduce backtracking in no-match case (for example, ##IF witout ##ENDIF##). If no-matches can't occur then atomic group can be omitted.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.