简体   繁体   中英

PHP: preg_replace problem with bracket interaction ')'

im trying to replicate blade from laravel in order to learn but i have encountered a problem

when using preg_replace to create the parser everything goes well except for a certain interaction with a bracket; ')'

ThisIsGonnaBeParsed.php

@if ($user->loggedIn() || true)

    <p>welcome {{$user->name}}</p>

@endif

@if (true)

    <p>hello</p>

@endif

PATTERN => REPLACE

        '/{{(.+?)}}/s'              => '<?php echo \1; ?>',
        '/@if(\s|)\((.+?)\)/s'      => '<?php if (\2): ?>',
        '/@endif/'                  => '<?php endif; ?>'

as you can see, everything is replaced except for the stuff stored between the brackets. but something goes wrong in the results.

FULL RESULT

<?php if ($user->loggedIn(): ?> || true)

    <p>welcome <?php echo $user->name; ?></p>

<?php endif; ?>

<?php if (true): ?>

    <p>hello</p>

<?php endif; ?>

THE PART WITH THE ERROR

<?php if ($user->loggedIn(): ?> || true)

as you can see, as soon as it encountered the ) it threw everything from that point on at the back of the string

THE RESULT I ACTUALLY WANTED

<?php if ($user->loggedIn() || true): ?> 

i have tried googling but i couldnt find any results

Your problem is that your inside parentheses match .+? is not greedy, so it stops at the first ) which is the one at the end of $user->loggedIn() . You can resolve that by using a greedy match, but you also need to remove the s modifier which allows . to match newline as that will otherwise cause it to match up to the ) at the end of if (true) . That will mean your if conditions cannot go over a line break, but if that is ok, then this should work:

$replacements = array(
        '/{{(.+?)}}/'              => '<?php echo $1; ?>',
        '/@if\s*\((.+)\)/'         => '<?php if ($1): ?>',
        '/@endif/'                 => '<?php endif; ?>'
    );

echo preg_replace(array_keys($replacements), $replacements, $code);

Output:

<?php if ($user->loggedIn() || true): ?>

    <p>welcome <?php echo $user->name; ?></p>

<?php endif; ?> 

<?php if (true): ?> 

    <p>hello</p> 

<?php endif; ?>

Demo on 3v4l.org

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM