Fiti Fiti - 3 months ago 14
PHP Question

regex to replace surrounded word multiple times

I'm trying to replace all "

&nbsp
" in twig syntax when it's surrounded by "
{%
" and "
%}
" or "
{{
" and "
}}
".

For example in the following string :

<p>{{ myFunction()&nbsp; }}</p>
<p>&nbsp;</p>
<p>{{ number|number_format(2, "&nbsp;.&nbsp;", '&nbsp;,&nbsp;')&nbsp;}}</p>
<p>{% set myVariable = '&nbsp;&nbsp;' %}</p>


i want to replace every "
&nbsp;
" by "
" except the "
<p>&nbsp;</p>
" one.

I'm doing the following :

$content = preg_replace('/({[{%].*)(&nbsp;)(.*[}%]})/', '$1 $3', $content);


but it replace only one occurence of "
&nbsp
" in each brackets surroundings. How to do it for everyones ?

Answer

Regex:

&nbsp;(?=(?:(?!{[{%]).)*[%}]})

Explanation:

&nbsp;              # Match non-breaking spaces (HTML entity)
(?=                 # Start of positive lookahead
    (?:                 # Start of non-capturing group (a)
        (?!{[{%])           # Asserts that next 2 characters are not {{ or {% (negative lookahead)
    .)*                 # Match any other characters (greedy) (except new-lines) (end of (a))
    [%}]}               # Up to a }} or %}
)                   # End of positive lookahead

In simple words it means all &nbsp;s that are finally followed by %} or }} and asserts they are within a {{...}} or {%...%} block.

Note

If you have ending delimiters not in the same line like below:

<p>{{ myFunction()&nbsp;

}}</p>    
<p>&nbsp;</p>    
<p>{{ number|number_format(2, "&nbsp;.&nbsp;", '&nbsp;,&nbsp;')&nbsp;

}}</p>    
<p>{% set myVariable = '&nbsp;&nbsp;'
%}</p>

Then you will need s modifier on by appending (?s) to regex:

(?s)&nbsp;(?=(?:(?!{[{%]).)*[%}]})

You may use it by default as well.

Live demo

PHP:

preg_replace('/&nbsp;(?=(?:(?!{[{%]).)*[%}]})/', ' ', $input);

Live demo