关于正则表达式,你找到{else}并允许嵌套

I created this pattern: {if ([^}]*)}((?:[\w\s]+[^}]*)){\/if}

but I have done a long time ago now, the pattern is, for example:

{if $module=admin}

{/if}

but I want to find:

{if $module=admin}

{else}

{/if}

as far as possible to find both with the same pattern.

Any ideas? thank you very much :)

/{if ([^}]+)}([\W\w]*?)(?:{else}([\W\w]*?))?{\/if}/g

  • {if Literal text.
  • ([^}]+) If condition: One or more non-closing-curly-brace (}) characters, all captured.
  • } Literal text.
  • ([\W\w]*?) Inside If: Zero or more characters. Match until the next part is found. (Very inefficient; you can rewrite to make this more performant.)
  • (?:{else}([\W\w]*?))? Optional group.
    • {else} Else: Literal text.
    • ([\W\w]*?) Inside Else: Zero or more characters. Match until the next part is found. (Very inefficient; you can rewrite to make this more performant.)
  • {\/if} Closing: Literal text.

/(?:{(?:if ([^}]+)|(else)|(\/if))}|^)([^{]*(?:(?!{(?:if|else|\/if)}){[^{]*)*)/g

Okay, this is way more complicated than the previous one, so I'll skip the full explanation for now (unless you request it later).

Basically, each match will give you a number of captured strings, in the following order:

  • Tag: (one of the following)
    • If start's condition (like $module=admin).
    • Else start
    • If end
    • Or none of the above.
  • Content: All content after the captured tag, up to the next special tag.
    • If there was no tag, this means the content that was captured is from the start of the input text up to the first If tag.
    • If the tag was If end, the content is just whatever comes after that specific tag. This could be useful or not, depending on how the input is structured.

This will give you all the pieces you need to implement your special {if} tags. I can give you pointers as what things you should think about, but I'll leave the PHP coding to you.


HINT: In your code, you can sort of build the structure of the document. For example:

[
  { content: "blah blah blah" },
  { if-condition: "module=page",
    content: ["after opening if, before else"],
    else-content: ["after else, before end of if", {
      if-condition: "page=4",
      content: ["nested content"]
    }]
  },
  { content: "end of file" }
]

Then you could loop over that and re-render it all however you like.