PHP - 正则表达式如何根据条件替换字符串

PHP - How can regex replace a string by condition

我有一个字符串:

{include "abc"}

{literal} 

function xyz() {

       "ok";

   }

{/literal}

{abc}

{123 }

我只想将所有 { 替换为 {{ 并将 } 替换为 }} 不在 {literal} 标签中。结果将是:

{{include "abc"}}

{{literal}}

   function xyz() {

       "ok";

   }

   //... something contain { and }

{{/literal}}

{{abc}}

{123 }}

有人可以帮助我,谢谢

正则表达式:

(?s)(?<=\{literal\}).*?(?=\{\/literal\})(*SKIP)(*F)|([{}])

替换字符串:


DEMO

你可以用这个模式来做:

$pattern = '~(?:(?<={literal})[^{]*(?:{(?!/literal})[^{]*)*+|[^{}]*)([{}])\K~'

$text = preg_replace($pattern, '', $text);

demo

图案详情:

~                       # pattern delimiter
(?:                     # non-capturing group
    (?<={literal})      # lookbehind: preceded by "{literal}"
                        # a lookbehind doesn't capture any thing, it is only a test
    [^{]*               # all that is not a {
    (?:
        {(?!/literal})  #/# a { not followed by "/literal}"
        [^{]*
    )*+                 # repeat as needed
  |                     # OR
    [^{}]*              # all that is not a curly bracket,
                        # (to quickly reach the next curly bracket)
)
([{}])                  # capture a { or a } in group 1
\K                      # discards all on the left from match result
                        # (so the whole match is empty and nothing is replaced,
                        # the content of the capture group is only added 
                        # with the replacement string '')
~

注意:此模式假定 {literal} 不能嵌套且始终关闭。如果 {literal} 可以保持未关闭状态,则可以强制执行此默认行为:"an unclosed {literal} is considered as open until the end of the string".

为此,您可以将捕获组更改为 ([{}]|(*COMMIT)(*F))。当第一个分支 [{}] 失败时,这意味着到达了字符串的末尾。 (*COMMIT) 动词强制正则表达式引擎在模式失败后停止字符串中的所有研究,并且 (*F) 强制它失败。所以在 {literal} 之后的所有内容都保持不变。