Search code examples
phppreg-replace-callback

php regex to replace spaces in braces including braces


I wonder if it's possible to solve such kind of template parsing using RegEx-es I have text similar to:

'Hello, {{ Na me|{{Surname }}}}. Would you like some drink? {{CoffeePreferred? We have a special discount for coffee}} {{Tea Preferred? We have a special discount for tea}}'

First, I need to fix errors in variable names (variables must always come right after braces to special symbol like "?" or "|" or something else could be comma or dot - it means rules can be added in future).

Na me, Tea Preferred Surname are spelling errors of variable names. Also variable names should start with right after curly braces contain no spaces after - otherwise it's also an error.

Then I need to keep text as is.

But Dear friend, We have a special discount for coffee and We have a special discount for tea are simple text.

So my question is how can I replace unnecessary spaces withing underscores in variables and keep them in text? Also I want to make it in as fewer steps as possible (due to performance impact and my texts can take megabytes).

I expect my text to be:

'Hello, {{Na_me|{{Surname}}}}. Would you like some drink? {{CoffeePreferred? We have a special discount for coffee}} {{Tea_Preferred? We have a special discount for tea}}'

My first step was to extract content of braces:

preg_replace_callback(
    '/(\{\{)(.*?)(\}\})/ui',
    function ($matches) {
        echo $matches[2];
});

Then I tried to replace spaces by rules described above with no success. I tried to use assertions like /[\s](?!<=\|)/ and expressions like (\s(?!\|))|((?!\|)\s) Does anybody have any idea?


Solution

  • Here is a way to do the job:

    $str = preg_replace_callback(
        '/\{\{([^|?{}]+)/',
        function ($matches) {
            $ret = trim($matches[1]);
            return preg_replace('/ /', '_', $ret);
        },
        $str
    );
    

    After that you can remove all the braces:

    $str = preg_replace('/[{}]+/', '', $str);