I’m writing a template compiler in PHP for my own personal projects and ran into an issue where my @if
directive doesn’t properly grab the contents of the directive if the condition ends with a )
.
private function handleIf(string $page): string
{
return preg_replace('/@if ?( ?(.*?) ?)(.*?)@endif/is', '<?php if ($1) { ?> $2 <?php } ?>', $page);
}
// the directive...
// @if(!empty($title))
// should result in
<?php !empty($title) { ?>
// but is instead rendered as
<?php !empty($title { ?>
// which obviously no worky
How would I adjust my regex to match this correctly? It has to be global and multiline since it’s part of a template. Is there another method I could use to extract directives?
2
Answers
Can see this code
input text
output
fully code:
can run via this link
https://rextester.com/DSN63422
For the given example, you could use a recursive pattern to match balanced parenthesis right after the
@if
.Note that you are matching php code with a regex that may give unexpected side effects.
@ifh*
Match@if
followed by optional spaces(
Capture group 1(
Match(
(
Capture group 2(?:[^()]++|(?1))*
Repeat matching any char except(
or)
or repeat the first sub pattern)
Close group 2)
Match)
)
Close group 1s*(.*?)s*
Capture group 3, match any character as few as possible between optional whitespace chars@endifb
Match@endif
followed by a word boundaryRegex demo | Php demo
Output
If you don’t want to cross another
@if(
in between:Regex demo