在php
我想用$
替换{{ $here $their '$literal' }}
中的$this->
。
这意味着我希望得到结果{{ $this->here $this->their '$literal' }}
,但我得到的是:{{ $this->here $their '$literal' }}
这是我的代码:
<?php
$str = '{{ $here $their "$literal" }}';
$search = '{{(?:\'[^\']+\'|"[^"]+")(*SKIP)(*F)|\$([0-9a-zA-Z_]++)}}';
$replace = '$this->$1';
// result is {{ $hello $this->by "$literal" }}
$result = preg_replace('/' . $search . '/U', $replace, $str);
?>
有没有人知道如何替换{{}}中未引用的多个匹配项?
答案 0 :(得分:1)
匹配{{...}}
中的preg_replace_callback
个子字符串,然后在anonynous方法中使用preg_replace
,并使用位调整的正则表达式:
$str = '{{ $here $their "$literal" }}';
echo preg_replace_callback('~{{.*?}}~s', function($m) {
return preg_replace('~(?:\'[^\']+\'|"[^"]+")(*SKIP)(*F)|\$\b~', '$this->$0', $m[0]);
}, $str);
请参阅PHP demo
'~{{.*?}}~s'
正则表达式会匹配{{
的非重叠事件,任何0 +字符尽可能少,直到第一个}}
。 preg_replace
内的正则表达式有点复杂:
(?:\'[^\']+\'|"[^"]+")(*SKIP)(*F)
- '
后跟1 {+ 1}}以外的1个字符,然后是'
(由于'
),或\'[^\']+\'
使用除"
之外的1+个字符然后"
(由于"
),并且一旦该子字符串匹配,它就会被丢弃并且正则表达式引擎继续进行下一个匹配(由于"[^"]+"
)(*SKIP)(*F)
- 或|
- 一个\$\b
符号后跟一个单词字符。答案 1 :(得分:1)
如果你的字符串已经用双花括号括起来,你只需写下:
$pattern = '~[^"\'$]*+(?:"[^"]*"[^"\'$]*|\'[^\']*\'[^"\'$]*)*+\$\b\K~A';
$str = preg_replace($pattern, 'this->', $str);
但如果你的双花括号括号部分是一个较大的文字,而你不想替换大括号外的其他$var
,你需要这个:
$pattern = '~(?:\G(?!\A)|{{)[^"\'$}]*+(?:"[^"]*"[^"\'$}]*|\'[^\']*\'[^"\'$}]*)*+\$\b\K~';
使用相同的替换字符串。
模式1详细信息:
此模式匹配所有字符,直到$(包含)。避免引用部分的最简单方法是在一美元之前匹配所有部分,并使用\K
从匹配结果中删除所有部分。
A修饰符(类似于模式开头的\G
)确保所有匹配都是连续的(没有间隙)。
~ # pattern delimiter
[^"'$]*+ #"# all characters except quotes and dollars
(?: # quoted parts
"[^"]*" [^'"$]*
|
'[^']*' [^"'$]*
)*+
\$
\b # no need to write `[a-zA-Z0-9_]+` and to capture it
# after a literal "$" a word boundary suffices.
\K # KEEP: characters before this token are removed from the match result
~A # ANCHORED: force the matches to be contiguous from the start
# of the string until the last match. If one position fails, no
# more match are possible
答案 2 :(得分:0)
您可能需要以下内容:
$str = '{{ $here $their "$literal" }}';
$result = preg_replace('/(\$.*?)\s(\$.*?)/i', '$this->$1 $this->$2', $str);
<强>样本强>
http://ideone.com/DO45Se