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. 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);
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. 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" .
To do that you can change the capture group to ([{}]|(*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. So all after {literal}
stay unchanged.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.