正则表达式多次替换包围的单词

时间:2016-08-22 15:25:41

标签: php regex twig

我试图替换所有"  "当它被" {%"包围时,在twig语法中和" %}"或" {{"和" }}"。

例如,在以下字符串中:

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

我想替换每个&#34; &nbsp;&#34; by&#34; &#34;除了&#34; <p>&nbsp;</p>&#34;之一。

我正在做以下事情:

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

但它只替换了一次&#34; &nbsp&#34;在每个括号周围。

如何为所有人制作?

3 个答案:

答案 0 :(得分:6)

\G是你的朋友:

(?:(?:\{{2}|\{%)           # the start 
|
\G(?!\A))                  # or the beginning of the prev match
(?:(?!(?:\}{2}|%\})).)*?\K # do not overrun the closing parentheses
&nbsp;                     # match a &nbsp;

a demo on regex101.com

<小时/> 在PHP

<?php

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

$regex = '~
            (?:(?:\{{2}|\{%)
            |
            \G(?!\A))
            (?:(?!(?:\}{2}|%\})).)*?\K
            &nbsp;
          ~x';
$string = preg_replace($regex, ' ', $string);

?>

可以在ideone.com上找到完整的代码示例。

答案 1 :(得分:2)

正则表达式:

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

说明:

&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

简单来说,它意味着&nbsp;%}后面的所有}},并声明它们位于{{...}}或{%... %}阻止。

注意

如果你的结尾分隔符不在同一行,如下所示:

<p>{{ myFunction()&nbsp;

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

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

然后,您需要s修改符,方法是将(?s)附加到正则表达式:

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

您也可以默认使用它。

Live demo

PHP:

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

Live demo

答案 2 :(得分:2)

  

当我被&nbsp;{%%}{{包围时,我正在尝试用树枝语法替换所有}}

如果您正在寻找最简单的解决方案,请匹配所有以{{开头并以}}结尾的子字符串,或以{%开头的子字符串使用带有%}正则表达式的'~{{.*?}}|{%.*?%}~s'结束,并使用带有preg_replace_callback的模式,您可以在其中进一步操作匿名函数中的匹配值:

preg_replace_callback('~{{.*?}}|{%.*?%}~s', function ($m) {
     return str_replace('&nbsp;', '', $m[0]); 
}, $s);

请参阅PHP demo

模式详情

  • {{.*?}} - 匹配{{,然后尽可能少的任何0+字符(由于懒惰的*?量词),最接近}}
  • | - 或
  • {%.*?%} - 匹配{%,然后尽可能少的0个字符,最接近%}
  • ~s' - enables the DOTALL modifier so that。`也可以匹配换行符号。