简体   繁体   English

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

[英]PHP - How can regex replace a string by condition

I have a string: 我有一个字符串:

{include "abc"}

{literal} 

function xyz() {

       "ok";

   }

{/literal}

{abc}

{123 }

I just want to replace all { to {{ and } to }} not in {literal} tag. 我只想替换{literal}标签中的所有{{{}}} The result will be: 结果将是:

{{include "abc"}}

{{literal}}

   function xyz() {

       "ok";

   }

   //... something contain { and }

{{/literal}}

{{abc}}

{123 }}

Someone can help me, Thanks 有人可以帮助我,谢谢

You can do it with this pattern: 您可以使用以下模式进行操作:

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

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

demo 演示

pattern details: 图案细节:

~                       # 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 '$1')
~

Notes: this pattern assumes that {literal} can't be nested and always closed. 注意:此模式假定{literal}不能嵌套且始终关闭。 If {literal} can stay unclosed, it is possible to force this default behavior: "an unclosed {literal} is considered as open until the end of the string" . 如果{literal}可以保持未关闭状态,则可以强制执行以下默认行为: “未关闭的{literal}被视为处于打开状态,直到字符串结尾”

To do that you can change the capture group to ([{}]|(*COMMIT)(*F)) . 为此,您可以将捕获组更改为([{}]|(*COMMIT)(*F)) When the first branch [{}] fails, this means that the end of the string is reached. 当第一个分支[{}]失败时,这意味着到达字符串的结尾。 The (*COMMIT) verb forces the regex engine to stop all research in the string when the pattern fails after, and (*F) forces it to fail. (*COMMIT)动词在模式失败后强制正则表达式引擎停止字符串中的所有研究,而(*F)强制其失败。 So all after {literal} stay unchanged. 因此{literal}之后的所有内容保持不变。

Regex: 正则表达式:

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

Replacement string: 替换字符串:

\1\1

DEMO 演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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